|
1 | 1 | # Diagnostic and subdiagnostic structs
|
2 | 2 | rustc has three diagnostic traits that can be used to create diagnostics:
|
3 |
| -`Diagnostic`, `LintDiagnostic`, and `Subdiagnostic`. For simple diagnostics, |
4 |
| -instead of using the `Diag` API to create and emit diagnostics, |
5 |
| -derived impls can be used. They are only suitable for simple diagnostics that |
| 3 | +`Diagnostic`, `LintDiagnostic`, and `Subdiagnostic`. |
| 4 | + |
| 5 | +For simple diagnostics, |
| 6 | +derived impls can be used, e.g. `#[derive(Diagnostic)]`. They are only suitable for simple diagnostics that |
6 | 7 | don't require much logic in deciding whether or not to add additional
|
7 | 8 | subdiagnostics.
|
8 | 9 |
|
9 |
| -Such diagnostic can be translated into |
10 |
| -different languages and each has a slug that uniquely identifies the |
11 |
| -diagnostic. |
| 10 | +In cases where diagnostics require more complex or dynamic behavior, such as conditionally adding subdiagnostics, |
| 11 | +customizing the rendering logic, or selecting messages at runtime, you will need to manually implement |
| 12 | +the corresponding trait (`Diagnostic`, `LintDiagnostic`, or `Subdiagnostic`). |
| 13 | +This approach provides greater flexibility and is recommended for diagnostics that go beyond simple, static structures. |
| 14 | + |
| 15 | +Diagnostic can be translated into different languages and each has a slug that uniquely identifies the diagnostic. |
12 | 16 |
|
13 | 17 | ## `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]`
|
14 | 18 |
|
@@ -142,7 +146,7 @@ tcx.dcx().emit_err(FieldAlreadyDeclared {
|
142 | 146 | });
|
143 | 147 | ```
|
144 | 148 |
|
145 |
| -### Reference |
| 149 | +### Reference for `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` |
146 | 150 | `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` support the
|
147 | 151 | following attributes:
|
148 | 152 |
|
@@ -330,7 +334,34 @@ function ([example][subdiag_use_1] and [example][subdiag_use_2]) on a
|
330 | 334 | diagnostic or by assigning it to a `#[subdiagnostic]`-annotated field of a
|
331 | 335 | diagnostic struct.
|
332 | 336 |
|
333 |
| -### Reference |
| 337 | +### Argument sharing and isolation |
| 338 | + |
| 339 | +Subdiagnostics will add their own arguments, |
| 340 | +i.e. some fields in their struct, into the subdiagnostic when rendering the message, |
| 341 | +so that the parameters in the main diagnostic can be used. |
| 342 | +However, when a subdiagnostic is added to a main diagnostic by implementing `#[derive(Subdiagnostic)]`, |
| 343 | +the following rules, introduced in [rust-lang/rust#142724](https://github.com/rust-lang/rust/pull/142724) |
| 344 | +apply to the handling of arguments (i.e., variables used in Fluent messages): |
| 345 | + |
| 346 | +**Argument isolation between sub diagnostics**: |
| 347 | +Arguments set by a subdiagnostic are only available during the rendering of that subdiagnostic. |
| 348 | +After the subdiagnostic is rendered, all arguments it introduced are restore from the main diagnostic. |
| 349 | +This ensures that multiple subdiagnostics do not pollute each other's argument scope. |
| 350 | +For example, when using a `Vec<Subdiag>`, it iteratively add the same arg over and over again. |
| 351 | + |
| 352 | +**Same argument override between sub and main diagnostics**: |
| 353 | +If a subdiagnostic sets a argument with the same name as a arg already in the master diagnostic, |
| 354 | +it will report an error at runtime unless both have exactly the same value. |
| 355 | +This |
| 356 | +- preserves the flexibility that can that *arguments is allowed to appear in the attributes of the subdiagnostic. |
| 357 | +For example, There is a attribute `#[suggestion(code = "{new_vis}")]` in sub-diagnostic, but `new_vis` is the field in main diagnostic struct. |
| 358 | +- prevents accidental overwriting or deletion of parameters required by the main diagnostic or other sub-diagnostics. |
| 359 | + |
| 360 | +These rules guarantee that arguments injected by subdiagnostics are strictly scoped to their own rendering. |
| 361 | +The main diagnostic's arguments remain unaffected by subdiagnostic logic, even in the presence of name collisions. |
| 362 | +Additionally, subdiagnostics can access parameters from the main diagnostic with the same name when needed. |
| 363 | + |
| 364 | +### Reference for `#[derive(Subdiagnostic)]` |
334 | 365 | `#[derive(Subdiagnostic)]` supports the following attributes:
|
335 | 366 |
|
336 | 367 | - `#[label(slug)]`, `#[help(slug)]`, `#[warning(slug)]` or `#[note(slug)]`
|
|
0 commit comments