Using typed identifiers instead of strings with the Fluent identifier
enables the diagnostic derive to benefit from the compile-time
validation that comes with typed identifiers - use of a non-existent
Fluent identifier will not compile.
Signed-off-by: David Wood <david.wood@huawei.com>
This commit makes type folding more like the way chalk does it.
Currently, `TypeFoldable` has `fold_with` and `super_fold_with` methods.
- `fold_with` is the standard entry point, and defaults to calling
`super_fold_with`.
- `super_fold_with` does the actual work of traversing a type.
- For a few types of interest (`Ty`, `Region`, etc.) `fold_with` instead
calls into a `TypeFolder`, which can then call back into
`super_fold_with`.
With the new approach, `TypeFoldable` has `fold_with` and
`TypeSuperFoldable` has `super_fold_with`.
- `fold_with` is still the standard entry point, *and* it does the
actual work of traversing a type, for all types except types of
interest.
- `super_fold_with` is only implemented for the types of interest.
Benefits of the new model.
- I find it easier to understand. The distinction between types of
interest and other types is clearer, and `super_fold_with` doesn't
exist for most types.
- With the current model is easy to get confused and implement a
`super_fold_with` method that should be left defaulted. (Some of the
precursor commits fixed such cases.)
- With the current model it's easy to call `super_fold_with` within
`TypeFolder` impls where `fold_with` should be called. The new
approach makes this mistake impossible, and this commit fixes a number
of such cases.
- It's potentially faster, because it avoids the `fold_with` ->
`super_fold_with` call in all cases except types of interest. A lot of
the time the compile would inline those away, but not necessarily
always.
There are two impls of the `Encoder` trait: `opaque::Encoder` and
`opaque::FileEncoder`. The former encodes into memory and is infallible, the
latter writes to file and is fallible.
Currently, standard `Result`/`?`/`unwrap` error handling is used, but this is a
bit verbose and has non-trivial cost, which is annoying given how rare failures
are (especially in the infallible `opaque::Encoder` case).
This commit changes how `Encoder` fallibility is handled. All the `emit_*`
methods are now infallible. `opaque::Encoder` requires no great changes for
this. `opaque::FileEncoder` now implements a delayed error handling strategy.
If a failure occurs, it records this via the `res` field, and all subsequent
encoding operations are skipped if `res` indicates an error has occurred. Once
encoding is complete, the new `finish` method is called, which returns a
`Result`. In other words, there is now a single `Result`-producing method
instead of many of them.
This has very little effect on how any file errors are reported if
`opaque::FileEncoder` has any failures.
Much of this commit is boring mechanical changes, removing `Result` return
values and `?` or `unwrap` from expressions. The more interesting parts are as
follows.
- serialize.rs: The `Encoder` trait gains an `Ok` associated type. The
`into_inner` method is changed into `finish`, which returns
`Result<Vec<u8>, !>`.
- opaque.rs: The `FileEncoder` adopts the delayed error handling
strategy. Its `Ok` type is a `usize`, returning the number of bytes
written, replacing previous uses of `FileEncoder::position`.
- Various methods that take an encoder now consume it, rather than being
passed a mutable reference, e.g. `serialize_query_result_cache`.
To render the message of a Fluent attribute, the identifier of the
Fluent message must be known. `DiagnosticMessage::FluentIdentifier`
contains both the message's identifier and optionally the identifier of
an attribute. Generated constants for each attribute would therefore
need to be named uniquely (amongst all error messages) or be able to
refer to only the attribute identifier which will be combined with a
message identifier later. In this commit, the latter strategy is
implemented as part of the `Diagnostic` type's functions for adding
subdiagnostics of various kinds.
Signed-off-by: David Wood <david.wood@huawei.com>
Adds a new `fluent_messages` macro which performs compile-time
validation of the compiler's Fluent resources (i.e. that the resources
parse and don't multiply define the same messages) and generates
constants that make using those messages in diagnostics more ergonomic.
For example, given the following invocation of the macro..
```ignore (rust)
fluent_messages! {
typeck => "./typeck.ftl",
}
```
..where `typeck.ftl` has the following contents..
```fluent
typeck-field-multiply-specified-in-initializer =
field `{$ident}` specified more than once
.label = used more than once
.label-previous-use = first use of `{$ident}`
```
...then the macro parse the Fluent resource, emitting a diagnostic if it
fails to do so, and will generate the following code:
```ignore (rust)
pub static DEFAULT_LOCALE_RESOURCES: &'static [&'static str] = &[
include_str!("./typeck.ftl"),
];
mod fluent_generated {
mod typeck {
pub const field_multiply_specified_in_initializer: DiagnosticMessage =
DiagnosticMessage::fluent("typeck-field-multiply-specified-in-initializer");
pub const field_multiply_specified_in_initializer_label_previous_use: DiagnosticMessage =
DiagnosticMessage::fluent_attr(
"typeck-field-multiply-specified-in-initializer",
"previous-use-label"
);
}
}
```
When emitting a diagnostic, the generated constants can be used as
follows:
```ignore (rust)
let mut err = sess.struct_span_err(
span,
fluent::typeck::field_multiply_specified_in_initializer
);
err.span_default_label(span);
err.span_label(
previous_use_span,
fluent::typeck::field_multiply_specified_in_initializer_label_previous_use
);
err.emit();
```
Signed-off-by: David Wood <david.wood@huawei.com>
With `ignore (rust)` rather than `ignore (pseudo-Rust)` my editor
highlights the code in the block, which is nicer.
Signed-off-by: David Wood <david.wood@huawei.com>
Manual implementors of translatable diagnostics will need to call
`set_arg`, not just the derive, so make this function a bit more
ergonomic by taking `IntoDiagnosticArg` rather than
`DiagnosticArgValue`.
Signed-off-by: David Wood <david.wood@huawei.com>
Type attributes could previously be used to support spanless
subdiagnostics but these couldn't easily be made optional in the same
way that spanned subdiagnostics could by using a field attribute on a
field with an `Option<Span>` type. Spanless subdiagnostics can now be
specified on fields with `()` type or `Option<()>` type.
Signed-off-by: David Wood <david.wood@huawei.com>
Diagnostics can have multiple primary spans, or have subdiagnostics
repeated at multiple locations, so support `Vec<..>` fields in the
diagnostic derive which become loops in the generated code.
Signed-off-by: David Wood <david.wood@huawei.com>
Add `#[subdiagnostic]` field attribute to the diagnostic derive which
is applied to fields that have types which use the subdiagnostic derive.
Signed-off-by: David Wood <david.wood@huawei.com>
In the initial implementation of the `SessionSubdiagnostic`, the
`Applicability` of a suggestion can be set both as a field and as part
of the attribute, this commit adds the same support to the original
`SessionDiagnostic` derive.
Signed-off-by: David Wood <david.wood@huawei.com>
`SetOnce` trait was introduced in the subdiagnostic derive to simplify
the code a little bit, re-use it in the diagnostic derive too.
Signed-off-by: David Wood <david.wood@huawei.com>
Remove some duplicated code between both diagnostic derives by
introducing helper functions for reporting an error in case of a invalid
attribute.
Signed-off-by: David Wood <david.wood@huawei.com>
Split `SessionDiagnostic` and `SessionSubdiagnostic` derives and the
various helper functions into multiple modules.
Signed-off-by: David Wood <david.wood@huawei.com>
Add a new derive, `#[derive(SessionSubdiagnostic)]`, which enables
deriving structs for labels, notes, helps and suggestions.
Signed-off-by: David Wood <david.wood@huawei.com>
Extends support for generating `DiagnosticMessage::FluentIdentifier`
messages from `SessionDiagnostic` derive to `#[suggestion]`.
Signed-off-by: David Wood <david.wood@huawei.com>
Extends support for generating `DiagnosticMessage::FluentIdentifier`
messages from `SessionDiagnostic` derive to `#[label]`.
Signed-off-by: David Wood <david.wood@huawei.com>
In an effort to make it easier to port diagnostics to
`SessionDiagnostic` (for translation) and since translation slugs could
replace error codes, make error codes optional in the
`SessionDiagnostic` derive.
Signed-off-by: David Wood <david.wood@huawei.com>
A call to `set_arg` is generated for every field of a
`SessionDiagnostic` struct without attributes, but not all types support
being an argument, so `#[no_arg]` is introduced to skip these fields.
Signed-off-by: David Wood <david.wood@huawei.com>
Small commit renaming `#[message]` to `#[primary_span]` as this more
accurately reflects what it does now.
Signed-off-by: David Wood <david.wood@huawei.com>
Small commit adding backticks around types and annotations in the error
messages from the session diagnostic derive.
Signed-off-by: David Wood <david.wood@huawei.com>
Non-subdiagnostic fields (i.e. those that don't have `#[label]`
attributes or similar and are just additional context) have to be added
as arguments for Fluent messages to refer them. This commit extends the
`SessionDiagnostic` derive to do this for all fields that do not have
attributes and introduces an `IntoDiagnosticArg` trait that is
implemented on all types that can be converted to a argument for Fluent.
Signed-off-by: David Wood <david.wood@huawei.com>
Move the handling of `Span` or `(Span, Applicability)` types in
`#[suggestion]` attributes to its own function.
Signed-off-by: David Wood <david.wood@huawei.com>
Various small changes to comments, like wrapping code in backticks,
changing comments to doc comments and adding newlines.
Signed-off-by: David Wood <david.wood@huawei.com>
Lint against more useless `#[must_use]` attributes
This expands the existing `#[must_use]` check in `unused_attributes` to lint against pretty much everything `#[must_use]` doesn't support.
Fixes#93906.
This expands the existing `#[must_use]` check in `unused_attributes`
to lint against pretty much everything `#[must_use]` doesn't support.
Fixes#93906.
Convert `newtype_index` to a proc macro
The `macro_rules!` implementation was becomng excessively complicated,
and difficult to modify. The new proc macro implementation should make
it much easier to add new features (e.g. skipping certain `#[derive]`s)
The `macro_rules!` implementation was becomng excessively complicated,
and difficult to modify. The new proc macro implementation should make
it much easier to add new features (e.g. skipping certain `#[derive]`s)
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
currently panics on failure (e.g. if the input is too short, or on a
bad `Result` discriminant), and in some places it returns an error
(e.g. on a bad `Option` discriminant). The number of places where
either happens is surprisingly small, just because the binary
representation has very little redundancy and a lot of input reading
can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
`.rlink` file production, and there's a `FIXME` comment suggesting it
should change to a binary format, and (b) in a few tests in
non-fundamental ways. Indeed #85993 is open to remove it entirely.
And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.
Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
optimization for small counts that the impl for `Result<T, E>` has,
because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
`collect`, which is nice; the one for `Vec` uses unsafe code, because
that gave better perf on some benchmarks.
Use field span in `rustc_macros` when emitting decode call
This will cause backtraces to point to the location of
the field in the struct/enum, rather than the derive macro.
This makes it clear which field was being decoded when the
backtrace was captured (which is especially useful if
there are multiple fields with the same type).
This will cause backtraces to point to the location of
the field in the struct/enum, rather than the derive macro.
This makes it clear which field was being decoded when the
backtrace was captured (which is especially useful if
there are multiple fields with the same type).
See #91867
This was mostly straightforward. In several places, I take advantage
of the fact that lifetimes are non-hygenic: a macro declares the
'tcx' lifetime, which is then used in types passed in as macro
arguments.
The PR had some unforseen perf regressions that are not as easy to find.
Revert the PR for now.
This reverts commit 6ae8912a3e, reversing
changes made to 86d6d2b738.
The previous macro_rules! parsers failed when an additional modifier was added
with ambiguity errors. The error is pretty unclear as to what exactly the cause
here is, but this change simplifies the argument parsing code such that the
error is avoided.
Using symbol::Interner makes it very easy to mixup UniqueTypeId symbols
with the global interner. In fact the Debug implementation of
UniqueTypeId did exactly this.
Using a separate interner type also avoids prefilling the interner with
unused symbols and allow for optimizing the symbol interner for parallel
access without negatively affecting the single threaded module codegen.
Preserve more spans in internal `rustc_queries!` macro
We now preserve the span of the various query modifiers, and
use the span of the query's name for the commas that we
generate to separate the modifiers. This makes debugging issues with the
internal query macro infrastructure much nicer - previously, we
would get errors messages pointing at the entire call site
(the `rustc_queries!` invocation), which isn't very useful.
This should have no effect when compilation succeeds.
A concrete example of an error message produced after this changed:
```
error: local ambiguity: multiple parsing options: built-in NTs tt ('modifiers') or 1 other option.
--> /home/aaron/repos/rust/compiler/rustc_middle/src/query/mod.rs:23:11
|
12 | / rustc_queries! {
13 | | query trigger_delay_span_bug(key: DefId) -> () {
14 | | desc { "trigger a delay span bug" }
15 | | }
... |
23 | | query hir_crate(key: ()) -> &'tcx Crate<'tcx> {
| | ^^^^^^^^^
... |
1715 | | }
1716 | | }
| |_- in this expansion of `rustc_query_append!`
|
::: compiler/rustc_query_impl/src/lib.rs:51:1
|
51 | rustc_query_append! { [define_queries!][<'tcx>] }
| ------------------------------------------------- in this macro invocation
```
The particular bug shown in this error message will be fixed
in a separate PR.
rfc3052 followup: Remove authors field from Cargo manifests
Since RFC 3052 soft deprecated the authors field, hiding it from
crates.io, docs.rs, and making Cargo not add it by default, and it is
not generally up to date/useful information for contributors, we may as well
remove it from crates in this repo.
Since RFC 3052 soft deprecated the authors field anyway, hiding it from
crates.io, docs.rs, and making Cargo not add it by default, and it is
not generally up to date/useful information, we should remove it from
crates in this repo.
We now preserve the span of the various query modifiers, and
use the span of the query's name for the commas that we
generate to separate the modifiers. This makes debugging issues with the
internal query macro infrastructure much nicer - previously, we
would get errors messages pointing at the entire call site
(the `rustc_queries!` invocation), which isn't very useful.
This should have no effect when compilation succeeds.
A concrete example of an error message produced after this changed:
```
error: local ambiguity: multiple parsing options: built-in NTs tt ('modifiers') or 1 other option.
--> /home/aaron/repos/rust/compiler/rustc_middle/src/query/mod.rs:23:11
|
12 | / rustc_queries! {
13 | | query trigger_delay_span_bug(key: DefId) -> () {
14 | | desc { "trigger a delay span bug" }
15 | | }
... |
23 | | query hir_crate(key: ()) -> &'tcx Crate<'tcx> {
| | ^^^^^^^^^
... |
1715 | | }
1716 | | }
| |_- in this expansion of `rustc_query_append!`
|
::: compiler/rustc_query_impl/src/lib.rs:51:1
|
51 | rustc_query_append! { [define_queries!][<'tcx>] }
| ------------------------------------------------- in this macro invocation
```
The particular bug shown in this error message will be fixed
in a separate PR.
- Replace {} with the stringified expr
Giant thank you to `@danielhenrymantilla` for figuring out how to make
this work ❤️
- Note that this is just an approximation and it would be better to add
a doc-comment
Currently, the rustc_macros::symbols macro generates two
`macro_rules!` macros as its output. These two macros are
used in rustc_span/src/symbol.rs.
This means that each Symbol that we define is represented
in the AST of rustc_symbols twice: once in the definition
of the `define_symbols!` macro (similarly for the
`keywords! macro), and once in the rustc_span::symbols
definition.
That would be OK if there were only a handful of symbols,
but currently we define over 1100 symbols. The definition
of the `define_symbols!` macro contains the expanded definition
of each symbol, so that's a lot of AST storage wasted on a
macro that is used exactly once.
This commit removes the `define_symbols` macro, and simply
allows the proc macro to directly generate the
`rustc_symbols::symbol::sym` module.
The benefit is mainly in reducing memory wasted during
compilation of rustc itself. It should also reduce memory used
by Rust Analyzer.
This commit also reduces the size of the AST for symbol
definitions, by moving two `#[allow(...)]` attributes from
the symbol constants to the `sym` module. This eliminates 2200+
attribute nodes.
This commit also eliminates the need for the `digits_array`
constant. There's no need to store an array of Symbol values
for digits. We can simply define a constant of the base value,
and add to that base value.
This improves how the `symbols` proc-macro handles errors.
If it finds an error in its input, the macro does not panic.
Instead, it still produces an output token stream. That token
stream will contain `compile_error!(...)` macro invocations.
This will still cause compilation to fail (which is what we want),
but it will prevent meaningless errors caused by the output not
containing symbols that the macro normally generates.
This solves a small (but annoying) problem. When you're editing
rustc_span/src/symbol.rs, and you get something wrong (dup
symbol name, misordered symbol), you want to get only the errors
that are relevant, not a burst of errors that are irrelevant.
This change also uses the correct Span when reporting errors,
so you get errors that point to the correct place in
rustc_span/src/symbol.rs where something is wrong.
This also adds several unit tests which test the `symbols` proc-macro.
This commit also makes it easy to run the `symbols` proc-macro
as an ordinary Cargo test. Just run `cargo test`. This makes it
easier to do development on the macro itself, such as running it
under a debugger.
This commit also uses the `Punctuated` type in `syn` for parsing
comma-separated lists, rather than doing it manually.
The output of the macro is not changed at all by this commit,
so rustc should be completely unchanged. This just improves
quality of life during development.
Introduce `TypeVisitor::BreakTy`
Implements MCP rust-lang/compiler-team#383.
r? `@ghost`
cc `@lcnr` `@oli-obk`
~~Blocked on FCP in rust-lang/compiler-team#383.~~
Add derive macro for specifying diagnostics using attributes.
Introduces `#[derive(SessionDiagnostic)]`, a derive macro for specifying structs that can be converted to Diagnostics using directions given by attributes on the struct and its fields. Currently, the following attributes have been implemented:
- `#[code = "..."]` -- this sets the Diagnostic's error code, and must be provided on the struct iself (ie, not on a field). Equivalent to calling `code`.
- `#[message = "..."]` -- this sets the Diagnostic's primary error message.
- `#[label = "..."]` -- this must be applied to fields of type `Span`, and is equivalent to `span_label`
- `#[suggestion(..)]` -- this allows a suggestion message to be supplied. This attribute must be applied to a field of type `Span` or `(Span, Applicability)`, and is equivalent to calling `span_suggestion`. Valid arguments are:
- `message = "..."` -- this sets the suggestion message.
- (Optional) `code = "..."` -- this suggests code for the suggestion. Defaults to empty.
`suggestion`also comes with other variants: `#[suggestion_short(..)]`, `#[suggestion_hidden(..)]` and `#[suggestion_verbose(..)]` which all take the same keys.
Within the strings passed to each attribute, fields can be referenced without needing to be passed explicitly into the format string -- eg, `#[error = "{ident} already declared"] ` will set the error message to `format!("{} already declared", &self.ident)`. Any fields on the struct can be referenced in this way.
Additionally, for any of these attributes, Option fields can be used to only optionally apply the decoration -- for example:
```rust
#[derive(SessionDiagnostic)]
#[code = "E0123"]
struct SomeKindOfError {
...
#[suggestion(message = "informative error message")]
opt_sugg: Option<(Span, Applicability)>
...
}
```
will not emit a suggestion if `opt_sugg` is `None`.
We plan on iterating on this macro further; this PR is a start.
Closes#61132.
r? `@oli-obk`
If a symbol name can only be imported from one place for a type, and
as long as it was not glob-imported anywhere in the current crate, we
can trim its printed path and print only the name.
This has wide implications on error messages with types, for example,
shortening `std::vec::Vec` to just `Vec`, as long as there is no other
`Vec` importable anywhere.
This adds a new '-Z trim-diagnostic-paths=false' option to control this
feature.
On the good path, with no diagnosis printed, we should try to avoid
issuing this query, so we need to prevent trimmed_def_paths query on
several cases.
This change also relies on a previous commit that differentiates
between `Debug` and `Display` on various rustc types, where the latter
is trimmed and presented to the user and the former is not.