Skip to content

Commit

Permalink
More updates for recent diagnostics changes.
Browse files Browse the repository at this point in the history
A sequel to rust-lang#1883, this covers diagnostic naming changes from
rust-lang/rust/pull/121489, rust-lang/rust/pull/121780, and
rust-lang/rust/pull/122132.
  • Loading branch information
nnethercote committed Mar 11, 2024
1 parent 020d4a8 commit f043b04
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 62 deletions.
8 changes: 4 additions & 4 deletions examples/rustc-driver-getting-diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ extern crate rustc_session;
extern crate rustc_span;

use rustc_errors::{
emitter::Emitter, registry, translation::Translate, DiagCtxt, Diagnostic, FluentBundle,
emitter::Emitter, registry, translation::Translate, DiagCtxt, DiagInner, FluentBundle,
};
use rustc_session::config;
use rustc_span::source_map::SourceMap;
Expand All @@ -22,7 +22,7 @@ use std::{

struct DebugEmitter {
source_map: Arc<SourceMap>,
diagnostics: Arc<Mutex<Vec<Diagnostic>>>,
diagnostics: Arc<Mutex<Vec<DiagInner>>>,
}

impl Translate for DebugEmitter {
Expand All @@ -36,7 +36,7 @@ impl Translate for DebugEmitter {
}

impl Emitter for DebugEmitter {
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
fn emit_diagnostic(&mut self, diag: &DiagInner) {
self.diagnostics.lock().unwrap().push(diag.clone());
}

Expand All @@ -52,7 +52,7 @@ fn main() {
.output()
.unwrap();
let sysroot = str::from_utf8(&out.stdout).unwrap().trim();
let buffer: Arc<Mutex<Vec<Diagnostic>>> = Arc::default();
let buffer: Arc<Mutex<Vec<DiagInner>>> = Arc::default();
let diagnostics = buffer.clone();
let config = rustc_interface::Config {
opts: config::Options {
Expand Down
2 changes: 1 addition & 1 deletion src/appendix/code-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Item | Kind | Short description | Chapter |
`ast::Crate` | struct | A syntax-level representation of a parsed crate | [The parser] | [compiler/rustc_ast/src/ast.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/struct.Crate.html)
`rustc_hir::Crate` | struct | A more abstract, compiler-friendly form of a crate's AST | [The Hir] | [compiler/rustc_hir/src/hir.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/struct.Crate.html)
`DefId` | struct | One of four types of HIR node identifiers | [Identifiers in the HIR] | [compiler/rustc_hir/src/def_id.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html)
`DiagnosticBuilder` | struct | A struct for building up compiler diagnostics, such as errors or lints | [Emitting Diagnostics] | [compiler/rustc_errors/src/diagnostic_builder.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.DiagnosticBuilder.html)
`Diag` | struct | A struct for a compiler diagnostic, such as an error or lint | [Emitting Diagnostics] | [compiler/rustc_errors/src/diagnostic.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html)
`DocContext` | struct | A state container used by rustdoc when crawling through a crate to gather its documentation | [Rustdoc] | [src/librustdoc/core.rs](https://github.com/rust-lang/rust/blob/master/src/librustdoc/core.rs)
`HirId` | struct | One of four types of HIR node identifiers | [Identifiers in the HIR] | [compiler/rustc_hir/src/hir_id.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir_id/struct.HirId.html)
`NodeId` | struct | One of four types of HIR node identifiers. Being phased out | [Identifiers in the HIR] | [compiler/rustc_ast/src/ast.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/node_id/struct.NodeId.html)
Expand Down
28 changes: 14 additions & 14 deletions src/diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,10 +315,10 @@ reporting errors.

[errors]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html

Diagnostics can be implemented as types which implement the `IntoDiagnostic`
Diagnostics can be implemented as types which implement the `Diagnostic`
trait. This is preferred for new diagnostics as it enforces a separation
between diagnostic emitting logic and the main code paths. For less-complex
diagnostics, the `IntoDiagnostic` trait can be derived -- see [Diagnostic
diagnostics, the `Diagnostic` trait can be derived -- see [Diagnostic
structs][diagnostic-structs]. Within the trait implementation, the APIs
described below can be used as normal.

Expand All @@ -335,27 +335,27 @@ In general, there are two classes of such methods: ones that emit an error
directly and ones that allow finer control over what to emit. For example,
[`span_err`][spanerr] emits the given error message at the given `Span`, but
[`struct_span_err`][strspanerr] instead returns a
[`DiagnosticBuilder`][diagbuild].
[`Diag`][diag].

Most of these methods will accept strings, but it is recommended that typed
identifiers for translatable diagnostics be used for new diagnostics (see
[Translation][translation]).

[translation]: ./diagnostics/translation.md

`DiagnosticBuilder` allows you to add related notes and suggestions to an error
`Diag` allows you to add related notes and suggestions to an error
before emitting it by calling the [`emit`][emit] method. (Failing to either
emit or [cancel][cancel] a `DiagnosticBuilder` will result in an ICE.) See the
[docs][diagbuild] for more info on what you can do.
emit or [cancel][cancel] a `Diag` will result in an ICE.) See the
[docs][diag] for more info on what you can do.

[spanerr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.DiagCtxt.html#method.span_err
[strspanerr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.DiagCtxt.html#method.struct_span_err
[diagbuild]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/diagnostic_builder/struct.DiagnosticBuilder.html
[emit]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/diagnostic_builder/struct.DiagnosticBuilder.html#method.emit
[cancel]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/diagnostic_builder/struct.DiagnosticBuilder.html#method.cancel
[diag]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html
[emit]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html#method.emit
[cancel]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html#method.cancel

```rust,ignore
// Get a DiagnosticBuilder. This does _not_ emit an error yet.
// Get a `Diag`. This does _not_ emit an error yet.
let mut err = sess.dcx.struct_span_err(sp, fluent::example::example_error);
// In some cases, you might need to check if `sp` is generated by a macro to
Expand Down Expand Up @@ -385,7 +385,7 @@ example-example-error = oh no! this is an error!

In addition to telling the user exactly _why_ their code is wrong, it's
oftentimes furthermore possible to tell them how to fix it. To this end,
`DiagnosticBuilder` offers a structured suggestions API, which formats code
`Diag` offers a structured suggestions API, which formats code
suggestions pleasingly in the terminal, or (when the `--error-format json` flag
is passed) as JSON for consumption by tools like [`rustfix`][rustfix].

Expand All @@ -395,7 +395,7 @@ Not all suggestions should be applied mechanically, they have a degree of
confidence in the suggested code, from high
(`Applicability::MachineApplicable`) to low (`Applicability::MaybeIncorrect`).
Be conservative when choosing the level. Use the
[`span_suggestion`][span_suggestion] method of `DiagnosticBuilder` to
[`span_suggestion`][span_suggestion] method of `Diag` to
make a suggestion. The last argument provides a hint to tools whether
the suggestion is mechanically applicable or not.

Expand All @@ -414,7 +414,7 @@ them))
- not shown (used for _very_ obvious cases, but we still want to allow tools to
apply them)

[span_suggestion]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.DiagnosticBuilder.html#method.span_suggestion
[span_suggestion]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html#method.span_suggestion

For example, to make our `qux` suggestion machine-applicable, we would do:

Expand Down Expand Up @@ -859,7 +859,7 @@ The "human" readable and the json format emitter can be found under
The JSON emitter defines [its own `Diagnostic`
struct](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/json/struct.Diagnostic.html)
(and sub-structs) for the JSON serialization. Don't confuse this with
[`errors::Diagnostic`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diagnostic.html)!
[`errors::Diag`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html)!

## `#[rustc_on_unimplemented(...)]`

Expand Down
44 changes: 21 additions & 23 deletions src/diagnostics/diagnostic-structs.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Diagnostic and subdiagnostic structs
rustc has three diagnostic derives that can be used to create simple diagnostics,
which are recommended to be used when they are applicable:
`#[derive(Diagnostic)]`, `#[derive(LintDiagnostic)]`, and `#[derive(Subdiagnostic)]`.
rustc has three diagnostic traits that can be used to create diagnostics:
`Diagnostic`, `LintDiagnostic`, and `Subdiagnostic`. For simple diagnostics,
instead of using the `Diag` API to create and emit diagnostics,
derived impls can be used. They are only suitable for simple diagnostics that
don't require much logic in deciding whether or not to add additional
subdiagnostics.

Diagnostics created with the derive macros can be translated into different
languages and each has a slug that uniquely identifies the diagnostic.
Such diagnostic can be translated into
different languages and each has a slug that uniquely identifies the
diagnostic.

## `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]`
Instead of using the `DiagnosticBuilder` API to create and emit diagnostics,
these derives can be used. They are only applicable for simple diagnostics that
don't require much logic in deciding whether or not to add additional
subdiagnostics.

Consider the [definition][defn] of the "field already declared" diagnostic
shown below:
Expand All @@ -28,14 +28,14 @@ pub struct FieldAlreadyDeclared {
}
```

`Diagnostic` can only be applied to structs and enums.
`Diagnostic` can only be derived on structs and enums.
Attributes that are placed on the type for structs are placed on each
variants for enums (or vice versa). Each `Diagnostic` has to have one
attribute, `#[diag(...)]`, applied to the struct or each enum variant.

If an error has an error code (e.g. "E0624"), then that can be specified using
the `code` sub-attribute. Specifying a `code` isn't mandatory, but if you are
porting a diagnostic that uses `DiagnosticBuilder` to use `Diagnostic`
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
Expand Down Expand Up @@ -110,13 +110,12 @@ the value of the `field_name` field of the struct), not a Fluent identifier.
cannot be used when the field's type contains an `Applicability`.

In the end, the `Diagnostic` derive will generate an implementation of
`IntoDiagnostic` that looks like the following:
`Diagnostic` that looks like the following:

```rust,ignore
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a> for FieldAlreadyDeclared {
fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
let mut diag =
DiagnosticBuilder::new(dcx, level, fluent::hir_analysis_field_already_declared);
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);
diag.set_span(self.span);
diag.span_label(
self.span,
Expand Down Expand Up @@ -208,7 +207,7 @@ following attributes:
- String which must be one of `machine-applicable`, `maybe-incorrect`,
`has-placeholders` or `unspecified`.
- `#[subdiagnostic]`
- _Applied to a type that implements `AddToDiagnostic` (from
- _Applied to a type that implements `Subdiagnostic` (from
`#[derive(Subdiagnostic)]`)._
- Adds the subdiagnostic represented by the subdiagnostic struct.
- `#[primary_span]` (_Optional_)
Expand Down Expand Up @@ -246,7 +245,7 @@ pub enum ExpectedReturnTypeLabel<'tcx> {
}
```

Like `Diagnostic`, `Subdiagnostic` can be applied to structs or
Like `Diagnostic`, `Subdiagnostic` can be derived for structs or
enums. Attributes that are placed on the type for structs are placed on each
variants for enums (or vice versa). Each `Subdiagnostic` should have one
attribute applied to the struct or each variant, one of:
Expand Down Expand Up @@ -307,12 +306,12 @@ Applicabilities can also be specified as a field (of type `Applicability`)
using the `#[applicability]` attribute.

In the end, the `Subdiagnostic` derive will generate an implementation
of `AddToDiagnostic` that looks like the following:
of `Subdiagnostic` that looks like the following:

```rust
impl<'tcx> AddToDiagnostic for ExpectedReturnTypeLabel<'tcx> {
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
use rustc_errors::{Applicability, IntoDiagnosticArg};
impl<'tcx> Subdiagnostic for ExpectedReturnTypeLabel<'tcx> {
fn add_to_diag(self, diag: &mut rustc_errors::Diagnostic) {
use rustc_errors::{Applicability, IntoDiagArg};
match self {
ExpectedReturnTypeLabel::Unit { span } => {
diag.span_label(span, rustc_errors::fluent::hir_analysis_expected_default_return_type)
Expand All @@ -321,7 +320,6 @@ impl<'tcx> AddToDiagnostic for ExpectedReturnTypeLabel<'tcx> {
diag.set_arg("expected", expected);
diag.span_label(span, rustc_errors::fluent::hir_analysis_expected_return_type)
}

}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/diagnostics/error-guaranteed.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ Thankfully, in most cases, it should be statically impossible to abuse

[errorguar]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.ErrorGuaranteed.html
[rerrors]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html
[emit]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/diagnostic_builder/struct.DiagnosticBuilder.html#method.emit
[emit]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.diag.html#method.emit
34 changes: 17 additions & 17 deletions src/diagnostics/translation.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ There are two ways of writing translatable diagnostics:
deciding to emit subdiagnostics and can therefore be represented as
diagnostic structs). See [the diagnostic and subdiagnostic structs
documentation](./diagnostic-structs.md).
2. Using typed identifiers with `DiagnosticBuilder` APIs (in
`IntoDiagnostic` or `AddToDiagnostic` or `DecorateLint` implementations).
2. Using typed identifiers with `Diag` APIs (in
`Diagnostic` or `Subdiagnostic` or `LintDiagnostic` implementations).

When adding or changing a translatable diagnostic,
you don't need to worry about the translations.
Expand Down Expand Up @@ -113,28 +113,28 @@ translation.
### Messages

All of rustc's traditional diagnostic APIs (e.g. `struct_span_err` or `note`)
take any message that can be converted into a `DiagnosticMessage` (or
`SubdiagnosticMessage`).
take any message that can be converted into a `DiagMessage` (or
`SubdiagMessage`).

[`rustc_error_messages::DiagnosticMessage`] can represent legacy non-translatable
[`rustc_error_messages::DiagMessage`] can represent legacy non-translatable
diagnostic messages and translatable messages. Non-translatable messages are
just `String`s. Translatable messages are just a `&'static str` with the
identifier of the Fluent message (sometimes with an additional `&'static str`
with an attribute).

`DiagnosticMessage` never needs to be interacted with directly:
`DiagnosticMessage` constants are created for each diagnostic message in a
Fluent resource (described in more detail below), or `DiagnosticMessage`s will
`DiagMessage` never needs to be interacted with directly:
`DiagMessage` constants are created for each diagnostic message in a
Fluent resource (described in more detail below), or `DiagMessage`s will
either be created in the macro-generated code of a diagnostic derive.

`rustc_error_messages::SubdiagnosticMessage` is similar, it can correspond to a
`rustc_error_messages::SubdiagMessage` is similar, it can correspond to a
legacy non-translatable diagnostic message or the name of an attribute to a
Fluent message. Translatable `SubdiagnosticMessage`s must be combined with a
`DiagnosticMessage` (using `DiagnosticMessage::with_subdiagnostic_message`) to
Fluent message. Translatable `SubdiagMessage`s must be combined with a
`DiagMessage` (using `DiagMessage::with_subdiagnostic_message`) to
be emitted (an attribute name on its own is meaningless without a corresponding
message identifier, which is what `DiagnosticMessage` provides).
message identifier, which is what `DiagMessage` provides).

Both `DiagnosticMessage` and `SubdiagnosticMessage` implement `Into` for any
Both `DiagMessage` and `SubdiagMessage` implement `Into` for any
type that can be converted into a string, and converts these into
non-translatable diagnostics - this keeps all existing diagnostic calls
working.
Expand All @@ -148,8 +148,8 @@ Diagnostics have a `set_arg` function that can be used to provide this
additional context to a diagnostic.

Arguments have both a name (e.g. "what" in the earlier example) and a value.
Argument values are represented using the `DiagnosticArgValue` type, which is
just a string or a number. rustc types can implement `IntoDiagnosticArg` with
Argument values are represented using the `DiagArgValue` type, which is
just a string or a number. rustc types can implement `IntoDiagArg` with
conversion into a string or a number, and common types like `Ty<'tcx>` already
have such implementations.

Expand All @@ -167,7 +167,7 @@ accessing the fallback and primary fluent bundles (`fallback_fluent_bundle` and
`fluent_bundle` respectively).

`Emitter` also has member functions with default implementations for performing
translation of a `DiagnosticMessage` using the results of
translation of a `DiagMessage` using the results of
`fallback_fluent_bundle` and `fluent_bundle`.

All of the emitters in rustc load the fallback Fluent bundle lazily, only
Expand Down Expand Up @@ -201,4 +201,4 @@ files are malformed, or a message is duplicated in multiple resources.
[Fluent]: https://projectfluent.org
[`compiler/rustc_borrowck/messages.ftl`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_borrowck/messages.ftl
[`compiler/rustc_parse/messages.ftl`]: https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc_parse/messages.ftl
[`rustc_error_messages::DiagnosticMessage`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_error_messages/enum.DiagnosticMessage.html
[`rustc_error_messages::DiagMessage`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_error_messages/enum.DiagMessage.html
4 changes: 2 additions & 2 deletions src/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Macro-expansion, `AST`-validation, name-resolution, and early linting also take
place during the lexing and parsing stage.

The [`rustc_ast::ast`]::{[`Crate`], [`Expr`], [`Pat`], ...} `AST` nodes are
returned from the parser while the standard [`DiagnosticBuilder`] API is used
returned from the parser while the standard [`Diag`] API is used
for error handling. Generally Rust's compiler will try to recover from errors
by parsing a superset of Rust's grammar, while also emitting an error type.

Expand Down Expand Up @@ -137,7 +137,7 @@ the final binary.
[`bump`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html#method.bump
[`check`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html#method.check
[`Crate`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_ast/ast/struct.Crate.html
[`DiagnosticBuilder`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_errors/struct.DiagnosticBuilder.html
[`diag`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.Diag.html
[`eat`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html#method.eat
[`expect`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_parse/parser/struct.Parser.html#method.expect
[`Expr`]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_ast/ast/struct.Expr.html
Expand Down

0 comments on commit f043b04

Please sign in to comment.