Merge pull request #2768 from rust-lang/diags
Update diagnostics documentation
This commit is contained in:
commit
400a96e441
2 changed files with 56 additions and 134 deletions
|
|
@ -12,7 +12,7 @@ customizing the rendering logic, or selecting messages at runtime, you will need
|
|||
the corresponding trait (`Diagnostic`, `LintDiagnostic`, or `Subdiagnostic`).
|
||||
This approach provides greater flexibility and is recommended for diagnostics that go beyond simple, static structures.
|
||||
|
||||
Diagnostic can be translated into different languages and each has a slug that uniquely identifies the diagnostic.
|
||||
Diagnostic can be translated into different languages.
|
||||
|
||||
## `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]`
|
||||
|
||||
|
|
@ -21,13 +21,13 @@ shown below:
|
|||
|
||||
```rust,ignore
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_field_already_declared, code = E0124)]
|
||||
#[diag("field `{$field_name}` is already declared", code = E0124)]
|
||||
pub struct FieldAlreadyDeclared {
|
||||
pub field_name: Ident,
|
||||
#[primary_span]
|
||||
#[label]
|
||||
#[label("field already declared")]
|
||||
pub span: Span,
|
||||
#[label(previous_decl_label)]
|
||||
#[label("`{$field_name}` first declared here")]
|
||||
pub prev_span: Span,
|
||||
}
|
||||
```
|
||||
|
|
@ -42,25 +42,10 @@ the `code` sub-attribute. Specifying a `code` isn't mandatory, but if you are
|
|||
porting a diagnostic that uses `Diag` to use `Diagnostic`
|
||||
then you should keep the code if there was one.
|
||||
|
||||
`#[diag(..)]` must provide a slug as the first positional argument (a path to an
|
||||
item in `rustc_errors::fluent::*`). A slug uniquely identifies the diagnostic
|
||||
and is also how the compiler knows what error message to emit (in the default
|
||||
locale of the compiler, or in the locale requested by the user). See
|
||||
`#[diag(..)]` must provide a message as the first positional argument.
|
||||
The message is written in English, but might be translated to the locale requested by the user. See
|
||||
[translation documentation](./translation.md) to learn more about how
|
||||
translatable error messages are written and how slug items are generated.
|
||||
|
||||
In our example, the Fluent message for the "field already declared" diagnostic
|
||||
looks like this:
|
||||
|
||||
```fluent
|
||||
hir_analysis_field_already_declared =
|
||||
field `{$field_name}` is already declared
|
||||
.label = field already declared
|
||||
.previous_decl_label = `{$field_name}` first declared here
|
||||
```
|
||||
|
||||
`hir_analysis_field_already_declared` is the slug from our example and is followed
|
||||
by the diagnostic message.
|
||||
translatable error messages are written and how they are generated.
|
||||
|
||||
Every field of the `Diagnostic` which does not have an annotation is
|
||||
available in Fluent messages as a variable, like `field_name` in the example
|
||||
|
|
@ -76,13 +61,7 @@ specified on a `Diagnostic`.
|
|||
|
||||
`#[label]`, `#[help]`, `#[warning]` and `#[note]` can all be applied to fields which have the
|
||||
type `Span`. Applying any of these attributes will create the corresponding
|
||||
subdiagnostic with that `Span`. These attributes will look for their
|
||||
diagnostic message in a Fluent attribute attached to the primary Fluent
|
||||
message. In our example, `#[label]` will look for
|
||||
`hir_analysis_field_already_declared.label` (which has the message "field already
|
||||
declared"). If there is more than one subdiagnostic of the same type, then
|
||||
these attributes can also take a value that is the attribute name to look for
|
||||
(e.g. `previous_decl_label` in our example).
|
||||
subdiagnostic with that `Span`. These attributes take a diagnostic message as an argument.
|
||||
|
||||
Other types have special behavior when used in a `Diagnostic` derive:
|
||||
|
||||
|
|
@ -99,17 +78,17 @@ represent optional `#[note]`/`#[help]`/`#[warning]` subdiagnostics.
|
|||
|
||||
Suggestions can be emitted using one of four field attributes:
|
||||
|
||||
- `#[suggestion(slug, code = "...", applicability = "...")]`
|
||||
- `#[suggestion_hidden(slug, code = "...", applicability = "...")]`
|
||||
- `#[suggestion_short(slug, code = "...", applicability = "...")]`
|
||||
- `#[suggestion_verbose(slug, code = "...", applicability = "...")]`
|
||||
- `#[suggestion("message", code = "...", applicability = "...")]`
|
||||
- `#[suggestion_hidden("message", code = "...", applicability = "...")]`
|
||||
- `#[suggestion_short("message", code = "...", applicability = "...")]`
|
||||
- `#[suggestion_verbose("message", code = "...", applicability = "...")]`
|
||||
|
||||
Suggestions must be applied on either a `Span` field or a `(Span,
|
||||
MachineApplicability)` field. Similarly to other field attributes, the slug
|
||||
specifies the Fluent attribute with the message and defaults to the equivalent
|
||||
of `.suggestion`. `code` specifies the code that should be suggested as a
|
||||
MachineApplicability)` field. Similarly to other field attributes, a message
|
||||
needs to be provided which will be shown to the user.
|
||||
`code` specifies the code that should be suggested as a
|
||||
replacement and is a format string (e.g. `{field_name}` would be replaced by
|
||||
the value of the `field_name` field of the struct), not a Fluent identifier.
|
||||
the value of the `field_name` field of the struct).
|
||||
`applicability` can be used to specify the applicability in the attribute, it
|
||||
cannot be used when the field's type contains an `Applicability`.
|
||||
|
||||
|
|
@ -119,15 +98,15 @@ In the end, the `Diagnostic` derive will generate an implementation of
|
|||
```rust,ignore
|
||||
impl<'a, G: EmissionGuarantee> Diagnostic<'a> for FieldAlreadyDeclared {
|
||||
fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
|
||||
let mut diag = Diag::new(dcx, level, fluent::hir_analysis_field_already_declared);
|
||||
let mut diag = Diag::new(dcx, level, "field `{$field_name}` is already declared");
|
||||
diag.set_span(self.span);
|
||||
diag.span_label(
|
||||
self.span,
|
||||
fluent::hir_analysis_label
|
||||
"field already declared"
|
||||
);
|
||||
diag.span_label(
|
||||
self.prev_span,
|
||||
fluent::hir_analysis_previous_decl_label
|
||||
"`{$field_name}` first declared here"
|
||||
);
|
||||
diag
|
||||
}
|
||||
|
|
@ -150,60 +129,40 @@ tcx.dcx().emit_err(FieldAlreadyDeclared {
|
|||
`#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` support the
|
||||
following attributes:
|
||||
|
||||
- `#[diag(slug, code = "...")]`
|
||||
- `#[diag("message", code = "...")]`
|
||||
- _Applied to struct or enum variant._
|
||||
- _Mandatory_
|
||||
- Defines the text and error code to be associated with the diagnostic.
|
||||
- Slug (_Mandatory_)
|
||||
- Uniquely identifies the diagnostic and corresponds to its Fluent message,
|
||||
mandatory.
|
||||
- A path to an item in `rustc_errors::fluent`, e.g.
|
||||
`rustc_errors::fluent::hir_analysis_field_already_declared`
|
||||
(`rustc_errors::fluent` is implicit in the attribute, so just
|
||||
`hir_analysis_field_already_declared`).
|
||||
- Message (_Mandatory_)
|
||||
- The diagnostic message which will be shown to the user.
|
||||
- See [translation documentation](./translation.md).
|
||||
- `code = "..."` (_Optional_)
|
||||
- Specifies the error code.
|
||||
- `#[note]` or `#[note(slug)]` (_Optional_)
|
||||
- `#[note("message")]` (_Optional_)
|
||||
- _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._
|
||||
- Adds a note subdiagnostic.
|
||||
- Value is a path to an item in `rustc_errors::fluent` for the note's
|
||||
message.
|
||||
- Defaults to equivalent of `.note`.
|
||||
- Value is the note's message.
|
||||
- If applied to a `Span` field, creates a spanned note.
|
||||
- `#[help]` or `#[help(slug)]` (_Optional_)
|
||||
- `#[help("message")]` (_Optional_)
|
||||
- _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._
|
||||
- Adds a help subdiagnostic.
|
||||
- Value is a path to an item in `rustc_errors::fluent` for the note's
|
||||
message.
|
||||
- Defaults to equivalent of `.help`.
|
||||
- Value is the help message.
|
||||
- If applied to a `Span` field, creates a spanned help.
|
||||
- `#[label]` or `#[label(slug)]` (_Optional_)
|
||||
- `#[label("message")]` (_Optional_)
|
||||
- _Applied to `Span` fields._
|
||||
- Adds a label subdiagnostic.
|
||||
- Value is a path to an item in `rustc_errors::fluent` for the note's
|
||||
message.
|
||||
- Defaults to equivalent of `.label`.
|
||||
- `#[warning]` or `#[warning(slug)]` (_Optional_)
|
||||
- Value is the label's message.
|
||||
- `#[warning("message")]` (_Optional_)
|
||||
- _Applied to struct or struct fields of type `Span`, `Option<()>` or `()`._
|
||||
- Adds a warning subdiagnostic.
|
||||
- Value is a path to an item in `rustc_errors::fluent` for the note's
|
||||
message.
|
||||
- Defaults to equivalent of `.warn`.
|
||||
- `#[suggestion{,_hidden,_short,_verbose}(slug, code = "...", applicability = "...")]`
|
||||
- Value is the warning's message.
|
||||
- `#[suggestion{,_hidden,_short,_verbose}("message", code = "...", applicability = "...")]`
|
||||
(_Optional_)
|
||||
- _Applied to `(Span, MachineApplicability)` or `Span` fields._
|
||||
- Adds a suggestion subdiagnostic.
|
||||
- Slug (_Mandatory_)
|
||||
- A path to an item in `rustc_errors::fluent`, e.g.
|
||||
`rustc_errors::fluent::hir_analysis_field_already_declared`
|
||||
(`rustc_errors::fluent` is implicit in the attribute, so just
|
||||
`hir_analysis_field_already_declared`). Fluent attributes for all messages
|
||||
exist as top-level items in that module (so `hir_analysis_message.attr` is just
|
||||
`attr`).
|
||||
- Message (_Mandatory_)
|
||||
- Value is the suggestion message that will be shown to the user.
|
||||
- See [translation documentation](./translation.md).
|
||||
- Defaults to `rustc_errors::fluent::_subdiag::suggestion` (or
|
||||
- `.suggestion` in Fluent).
|
||||
- `code = "..."`/`code("...", ...)` (_Mandatory_)
|
||||
- One or multiple format strings indicating the code to be suggested as a
|
||||
replacement. Multiple values signify multiple possible replacements.
|
||||
|
|
@ -235,12 +194,12 @@ shown below:
|
|||
```rust
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum ExpectedReturnTypeLabel<'tcx> {
|
||||
#[label(hir_analysis_expected_default_return_type)]
|
||||
#[label("expected `()` because of default return type")]
|
||||
Unit {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[label(hir_analysis_expected_return_type)]
|
||||
#[label("expected `{$expected}` because of return type")]
|
||||
Other {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
|
|
@ -260,21 +219,9 @@ attribute applied to the struct or each variant, one of:
|
|||
- `#[warning(..)]` for defining a warning
|
||||
- `#[suggestion{,_hidden,_short,_verbose}(..)]` for defining a suggestion
|
||||
|
||||
All of the above must provide a slug as the first positional argument (a path
|
||||
to an item in `rustc_errors::fluent::*`). A slug uniquely identifies the
|
||||
diagnostic and is also how the compiler knows what error message to emit (in
|
||||
the default locale of the compiler, or in the locale requested by the user).
|
||||
All of the above must provide a diagnostic message as the first positional argument.
|
||||
See [translation documentation](./translation.md) to learn more about how
|
||||
translatable error messages are written and how slug items are generated.
|
||||
|
||||
In our example, the Fluent message for the "expected return type" label
|
||||
looks like this:
|
||||
|
||||
```fluent
|
||||
hir_analysis_expected_default_return_type = expected `()` because of default return type
|
||||
|
||||
hir_analysis_expected_return_type = expected `{$expected}` because of return type
|
||||
```
|
||||
translatable error messages are generated.
|
||||
|
||||
Using the `#[primary_span]` attribute on a field (with type `Span`) will denote
|
||||
the primary span of the subdiagnostic. A primary span is only necessary for a
|
||||
|
|
@ -289,17 +236,15 @@ Like `Diagnostic`, `Subdiagnostic` supports `Option<T>` and
|
|||
|
||||
Suggestions can be emitted using one of four attributes on the type/variant:
|
||||
|
||||
- `#[suggestion(..., code = "...", applicability = "...")]`
|
||||
- `#[suggestion_hidden(..., code = "...", applicability = "...")]`
|
||||
- `#[suggestion_short(..., code = "...", applicability = "...")]`
|
||||
- `#[suggestion_verbose(..., code = "...", applicability = "...")]`
|
||||
- `#[suggestion("...", code = "...", applicability = "...")]`
|
||||
- `#[suggestion_hidden("...", code = "...", applicability = "...")]`
|
||||
- `#[suggestion_short("...", code = "...", applicability = "...")]`
|
||||
- `#[suggestion_verbose("...", code = "...", applicability = "...")]`
|
||||
|
||||
Suggestions require `#[primary_span]` be set on a field and can have the
|
||||
following sub-attributes:
|
||||
|
||||
- The first positional argument specifies the path to a item in
|
||||
`rustc_errors::fluent` corresponding to the Fluent attribute with the message
|
||||
and defaults to the equivalent of `.suggestion`.
|
||||
- The first positional argument specifies the message which will be shown to the user.
|
||||
- `code` specifies the code that should be suggested as a replacement and is a
|
||||
format string (e.g. `{field_name}` would be replaced by the value of the
|
||||
`field_name` field of the struct), not a Fluent identifier.
|
||||
|
|
@ -318,11 +263,11 @@ impl<'tcx> Subdiagnostic for ExpectedReturnTypeLabel<'tcx> {
|
|||
use rustc_errors::{Applicability, IntoDiagArg};
|
||||
match self {
|
||||
ExpectedReturnTypeLabel::Unit { span } => {
|
||||
diag.span_label(span, rustc_errors::fluent::hir_analysis_expected_default_return_type)
|
||||
diag.span_label(span, "expected `()` because of default return type")
|
||||
}
|
||||
ExpectedReturnTypeLabel::Other { span, expected } => {
|
||||
diag.set_arg("expected", expected);
|
||||
diag.span_label(span, rustc_errors::fluent::hir_analysis_expected_return_type)
|
||||
diag.span_label(span, "expected `{$expected}` because of return type")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -354,7 +299,7 @@ If a subdiagnostic sets a argument with the same name as a arguments already in
|
|||
it will report an error at runtime unless both have exactly the same value.
|
||||
It has two benefits:
|
||||
- preserves the flexibility that arguments in the main diagnostic are allowed to appear in the attributes of the subdiagnostic.
|
||||
For example, There is an attribute `#[suggestion(code = "{new_vis}")]` in the subdiagnostic, but `new_vis` is the field in the main diagnostic struct.
|
||||
For example, There is an attribute `#[suggestion("...", code = "{new_vis}")]` in the subdiagnostic, but `new_vis` is the field in the main diagnostic struct.
|
||||
- prevents accidental overwriting or deletion of arguments required by the main diagnostic or other subdiagnostics.
|
||||
|
||||
These rules guarantee that arguments injected by subdiagnostics are strictly scoped to their own rendering.
|
||||
|
|
@ -364,32 +309,20 @@ Additionally, subdiagnostics can access arguments from the main diagnostic with
|
|||
### Reference for `#[derive(Subdiagnostic)]`
|
||||
`#[derive(Subdiagnostic)]` supports the following attributes:
|
||||
|
||||
- `#[label(slug)]`, `#[help(slug)]`, `#[warning(slug)]` or `#[note(slug)]`
|
||||
- `#[label("message")]`, `#[help("message")]`, `#[warning("message")]` or `#[note("message")]`
|
||||
- _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._
|
||||
- _Mandatory_
|
||||
- Defines the type to be representing a label, help or note.
|
||||
- Slug (_Mandatory_)
|
||||
- Uniquely identifies the diagnostic and corresponds to its Fluent message,
|
||||
mandatory.
|
||||
- A path to an item in `rustc_errors::fluent`, e.g.
|
||||
`rustc_errors::fluent::hir_analysis_field_already_declared`
|
||||
(`rustc_errors::fluent` is implicit in the attribute, so just
|
||||
`hir_analysis_field_already_declared`).
|
||||
- Message (_Mandatory_)
|
||||
- The diagnostic message that will be shown to the user.
|
||||
- See [translation documentation](./translation.md).
|
||||
- `#[suggestion{,_hidden,_short,_verbose}(slug, code = "...", applicability = "...")]`
|
||||
- `#[suggestion{,_hidden,_short,_verbose}("message", code = "...", applicability = "...")]`
|
||||
- _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._
|
||||
- _Mandatory_
|
||||
- Defines the type to be representing a suggestion.
|
||||
- Slug (_Mandatory_)
|
||||
- A path to an item in `rustc_errors::fluent`, e.g.
|
||||
`rustc_errors::fluent::hir_analysis_field_already_declared`
|
||||
(`rustc_errors::fluent` is implicit in the attribute, so just
|
||||
`hir_analysis::field_already_declared`). Fluent attributes for all messages
|
||||
exist as top-level items in that module (so `hir_analysis_message.attr` is just
|
||||
`hir_analysis::attr`).
|
||||
- Message (_Mandatory_)
|
||||
- The diagnostic message that will be shown to the user.
|
||||
- See [translation documentation](./translation.md).
|
||||
- Defaults to `rustc_errors::fluent::_subdiag::suggestion` (or
|
||||
- `.suggestion` in Fluent).
|
||||
- `code = "..."`/`code("...", ...)` (_Mandatory_)
|
||||
- One or multiple format strings indicating the code to be suggested as a
|
||||
replacement. Multiple values signify multiple possible replacements.
|
||||
|
|
@ -401,11 +334,11 @@ Additionally, subdiagnostics can access arguments from the main diagnostic with
|
|||
- `maybe-incorrect`
|
||||
- `has-placeholders`
|
||||
- `unspecified`
|
||||
- `#[multipart_suggestion{,_hidden,_short,_verbose}(slug, applicability = "...")]`
|
||||
- `#[multipart_suggestion{,_hidden,_short,_verbose}("message", applicability = "...")]`
|
||||
- _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._
|
||||
- _Mandatory_
|
||||
- Defines the type to be representing a multipart suggestion.
|
||||
- Slug (_Mandatory_): see `#[suggestion]`
|
||||
- Message (_Mandatory_): see `#[suggestion]`
|
||||
- `applicability = "..."` (_Optional_): see `#[suggestion]`
|
||||
- `#[primary_span]` (_Mandatory_ for labels and suggestions; _optional_ otherwise; not applicable
|
||||
to multipart suggestions)
|
||||
|
|
|
|||
|
|
@ -13,10 +13,7 @@ active redesign proposals (as of
|
|||
Please see the tracking issue <https://github.com/rust-lang/rust/issues/132181>
|
||||
for status updates.
|
||||
|
||||
We have downgraded the internal lints `untranslatable_diagnostic` and
|
||||
`diagnostic_outside_of_impl`. Those internal lints previously required new code
|
||||
to use the current translation infrastructure. However, because the translation
|
||||
infra is waiting for a yet-to-be-proposed redesign and thus rework, we are not
|
||||
The translation infra is waiting for a yet-to-be-proposed redesign and thus rework, we are not
|
||||
mandating usage of current translation infra. Use the infra if you *want to* or
|
||||
otherwise makes the code cleaner, but otherwise sidestep the translation infra
|
||||
if you need more flexibility.
|
||||
|
|
@ -40,11 +37,6 @@ There are two ways of writing translatable diagnostics:
|
|||
When adding or changing a translatable diagnostic,
|
||||
you don't need to worry about the translations.
|
||||
Only updating the original English message is required.
|
||||
Currently,
|
||||
each crate which defines translatable diagnostics has its own Fluent resource,
|
||||
which is a file named `messages.ftl`,
|
||||
located in the root of the crate
|
||||
(such as`compiler/rustc_expand/messages.ftl`).
|
||||
|
||||
## Fluent
|
||||
|
||||
|
|
@ -118,11 +110,8 @@ information that needs to be provided by the code to do so.
|
|||
|
||||
### Compile-time validation and typed identifiers
|
||||
|
||||
rustc's `fluent_messages` macro performs compile-time validation of Fluent
|
||||
resources and generates code to make it easier to refer to Fluent messages in
|
||||
diagnostics.
|
||||
|
||||
Compile-time validation of Fluent resources will emit any parsing errors
|
||||
rustc's `#[derive(Diagnostic)]` macro performs compile-time validation of Fluent
|
||||
messages. Compile-time validation of Fluent resources will emit any parsing errors
|
||||
from Fluent resources while building the compiler, preventing invalid Fluent
|
||||
resources from causing panics in the compiler. Compile-time validation also
|
||||
emits an error if multiple Fluent messages have the same identifier.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue