Migrate most of `rustc_builtin_macros` to diagnostic impls
cc #100717
This is a couple of days work, but I decided to stop for now before the PR becomes too big. There's around 50 unresolved failures when `rustc::untranslatable_diagnostic` is denied, which I'll finish addressing once this PR goes thtough
A couple of outputs have changed, but in all instances I think the changes are an improvement/are more consistent with other diagnostics (although I'm happy to revert any which seem worse)
Instead of loading the Fluent resources for every crate in
`rustc_error_messages`, each crate generates typed identifiers for its
own diagnostics and creates a static which are pulled together in the
`rustc_driver` crate and provided to the diagnostic emitter.
Signed-off-by: David Wood <david.wood@huawei.com>
This allows porting uses of span_suggestions() to diagnostic structs.
Doesn't work for multipart_suggestions() because the rank would be
reversed - the struct would specify multiple spans, each of which has
multiple possible replacements, while multipart_suggestions() creates
multiple possible replacements, each with multiple spans.
Documentation comments shouldn't affect the diagnostic derive in any
way, but explicit support has to be added for ignoring the `doc`
attribute.
Signed-off-by: David Wood <david.wood@huawei.com>
Following the approach taken in earlier commits to separate formatting
initialization from use in the subdiagnostic derive, simplify the
diagnostic derive by removing the field-ordering logic that previously
solved this problem.
Signed-off-by: David Wood <david.wood@huawei.com>
Diagnostic derives have previously had to take special care when
ordering the generated code so that fields were not used after a move.
This is unlikely for most fields because a field is either annotated
with a subdiagnostic attribute and is thus likely a `Span` and copiable,
or is a argument, in which case it is only used once by `set_arg`
anyway.
However, format strings for code in suggestions can result in fields
being used after being moved if not ordered carefully. As a result, the
derive currently puts `set_arg` calls last (just before emission), such
as:
```rust
let diag = { /* create diagnostic */ };
diag.span_suggestion_with_style(
span,
fluent::crate::slug,
format!("{}", __binding_0),
Applicability::Unknown,
SuggestionStyle::ShowAlways
);
/* + other subdiagnostic additions */
diag.set_arg("foo", __binding_0);
/* + other `set_arg` calls */
diag.emit();
```
For eager translation, this doesn't work, as the message being
translated eagerly can assume that all arguments are available - so
arguments _must_ be set first.
Format strings for suggestion code are now separated into two parts - an
initialization line that performs the formatting into a variable, and a
usage in the subdiagnostic addition.
By separating these parts, the initialization can happen before
arguments are set, preserving the desired order so that code compiles,
while still enabling arguments to be set before subdiagnostics are
added.
```rust
let diag = { /* create diagnostic */ };
let __code_0 = format!("{}", __binding_0);
/* + other formatting */
diag.set_arg("foo", __binding_0);
/* + other `set_arg` calls */
diag.span_suggestion_with_style(
span,
fluent::crate::slug,
__code_0,
Applicability::Unknown,
SuggestionStyle::ShowAlways
);
/* + other subdiagnostic additions */
diag.emit();
```
Signed-off-by: David Wood <david.wood@huawei.com>
Add support for `eager` argument to the `subdiagnostic` attribute which
generates a call to `eager_subdiagnostic`.
Signed-off-by: David Wood <david.wood@huawei.com>
The macro warn_ was named like that because it the
keyword warn is a built-in attribute and at the time
this macro was created the word 'warning' was also
taken.
However it is no longer the case and we can rename
warn_ to warning.
Deriving SessionDiagnostic on a type no longer forces that diagnostic to
be one of warning, error, or fatal. The level is instead decided when
the struct is passed to the respective Handler::emit_*() method.
Both diagnostic and subdiagnostic derives were missing the ability to
add warnings to diagnostics - this is made more difficult by the `warn`
attribute already existing, so this name being unavailable for the
derives to use. `#[warn_]` is used instead, which requires
special-casing so that `{span_,}warn` is called instead of
`{span_,}warn_`.
Signed-off-by: David Wood <david.wood@huawei.com>
Add support for `MultiSpan` with any of the attributes that work on a
`Span` - requires that diagnostic logic generated for these attributes
are emitted in the by-move block rather than the by-ref block that they
would normally have been generated in.
Signed-off-by: David Wood <david.wood@huawei.com>
`SessionDiagnostic` isn't suitable for use on lints as whether or not it
creates an error or a warning is decided at compile-time by the macro,
whereas lints decide this at runtime based on the location of the lint
being reported (as it will depend on the user's `allow`/`deny`
attributes, etc). Re-using most of the machinery for
`SessionDiagnostic`, this macro introduces a `LintDiagnostic` derive
which implements a `DecorateLint` trait, taking a
`LintDiagnosticBuilder` and adding to the lint according to the
diagnostic struct.