Skip to content

Commit aabd3f5

Browse files
authored
Merge pull request #2480 from xizheyin/argument-sharing-and-isolation
Add `arguments sharing and isolation` section in `diagnostic-struct` of rdg
2 parents 3008550 + 58648c8 commit aabd3f5

File tree

1 file changed

+39
-8
lines changed

1 file changed

+39
-8
lines changed

src/diagnostics/diagnostic-structs.md

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
# Diagnostic and subdiagnostic structs
22
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
67
don't require much logic in deciding whether or not to add additional
78
subdiagnostics.
89

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

1317
## `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]`
1418

@@ -142,7 +146,7 @@ tcx.dcx().emit_err(FieldAlreadyDeclared {
142146
});
143147
```
144148

145-
### Reference
149+
### Reference for `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]`
146150
`#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` support the
147151
following attributes:
148152

@@ -330,7 +334,34 @@ function ([example][subdiag_use_1] and [example][subdiag_use_2]) on a
330334
diagnostic or by assigning it to a `#[subdiagnostic]`-annotated field of a
331335
diagnostic struct.
332336

333-
### Reference
337+
### Argument sharing and isolation
338+
339+
Subdiagnostics add their own arguments (i.e., certain fields in their structure) to the `Diag` structure before rendering the information.
340+
`Diag` structure also stores the arguments from the main diagnostic, so the subdiagnostic can also use the arguments from the main diagnostic.
341+
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 restored 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 adds the same argument 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 arguments already in the main diagnostic,
354+
it will report an error at runtime unless both have exactly the same value.
355+
It has two benefits:
356+
- preserves the flexibility that arguments in the main diagnostic are allowed to appear in the attributes of the subdiagnostic.
357+
For example, There is an attribute `#[suggestion(code = "{new_vis}")]` in the subdiagnostic, but `new_vis` is the field in the main diagnostic struct.
358+
- prevents accidental overwriting or deletion of arguments required by the main diagnostic or other subdiagnostics.
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 arguments from the main diagnostic with the same name when needed.
363+
364+
### Reference for `#[derive(Subdiagnostic)]`
334365
`#[derive(Subdiagnostic)]` supports the following attributes:
335366

336367
- `#[label(slug)]`, `#[help(slug)]`, `#[warning(slug)]` or `#[note(slug)]`

0 commit comments

Comments
 (0)