Error message all end up passing into a function as an `impl
Into<{D,Subd}iagnosticMessage>`. If an error message is creatd as
`&format("...")` that means we allocate a string (in the `format!`
call), then take a reference, and then clone (allocating again) the
reference to produce the `{D,Subd}iagnosticMessage`, which is silly.
This commit removes the leading `&` from a lot of these cases. This
means the original `String` is moved into the
`{D,Subd}iagnosticMessage`, avoiding the double allocations. This
requires changing some function argument types from `&str` to `String`
(when all arguments are `String`) or `impl
Into<{D,Subd}iagnosticMessage>` (when some arguments are `String` and
some are `&str`).
try to downgrade Arc -> Lrc -> Rc -> no-Rc in few places
Expecting this be not slower on non-parallel compiler and probably faster on parallel (checked that this PR builds on it).
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
My type ascription
Oh rip it out
Ah
If you think we live too much then
You can sacrifice diagnostics
Don't mix your garbage
Into my syntax
So many weird hacks keep diagnostics alive
Yet I don't even step outside
So many bad diagnostics keep tyasc alive
Yet tyasc doesn't even bother to survive!
Added byte position range for `proc_macro::Span`
Currently, the [`Debug`](https://doc.rust-lang.org/beta/proc_macro/struct.Span.html#impl-Debug-for-Span) implementation for [`proc_macro::Span`](https://doc.rust-lang.org/beta/proc_macro/struct.Span.html#) calls the debug function implemented in the trait implementation of `server::Span` for the type `Rustc` in the `rustc-expand` crate.
The current implementation, of the referenced function, looks something like this:
```rust
fn debug(&mut self, span: Self::Span) -> String {
if self.ecx.ecfg.span_debug {
format!("{:?}", span)
} else {
format!("{:?} bytes({}..{})", span.ctxt(), span.lo().0, span.hi().0)
}
}
```
It returns the byte position of the [`Span`](https://doc.rust-lang.org/beta/proc_macro/struct.Span.html#) as an interpolated string.
Because this is currently the only way to get a spans position in the file, I might lead someone, who is interested in this information, to parsing this interpolated string back into a range of bytes, which I think is a very non-rusty way.
The proposed `position()`, method implemented in this PR, gives the ability to directly get this info.
It returns a [`std::ops::Range`](https://doc.rust-lang.org/std/ops/struct.Range.html#) wrapping the lowest and highest byte of the [`Span`](https://doc.rust-lang.org/beta/proc_macro/struct.Span.html#).
I put it behind the `proc_macro_span` feature flag because many of the other functions that have a similar footprint also are annotated with it, I don't actually know if this is right.
It would be great if somebody could take a look at this, thank you very much in advanced.
Add `rustc_fluent_macro` to decouple fluent from `rustc_macros`
Fluent, with all the icu4x it brings in, takes quite some time to compile. `fluent_messages!` is only needed in further downstream rustc crates, but is blocking more upstream crates like `rustc_index`. By splitting it out, we allow `rustc_macros` to be compiled earlier, which speeds up `x check compiler` by about 5 seconds (and even more after the needless dependency on `serde_json` is removed from `rustc_data_structures`).
Fluent, with all the icu4x it brings in, takes quite some time to
compile. `fluent_messages!` is only needed in further downstream rustc
crates, but is blocking more upstream crates like `rustc_index`. By
splitting it out, we allow `rustc_macros` to be compiled earlier, which
speeds up `x check compiler` by about 5 seconds (and even more after the
needless dependency on `serde_json` is removed from
`rustc_data_structures`).
Improve the error message when forwarding a matched fragment to another macro
Adds a link to [Forwarding a matched fragment](https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment) section of the Rust Reference, and suggests a possible fix (using `:tt` instead in the macro definition).
Also removes typos from the original message, it should be `:lifetime` instead of `$lifetime`.
## Motivation
When trying to write a macro which uses a literal in the matcher from the outer macro, like the following one, using a fragment specified that isn't one of `:ident`, `:lifetime`, or `:tt` currently results in a hard to understand message.
```rs
macro_rules! make_t_for_all_tokens {
($($name:literal as $variant:expr,)*) => {
macro_rules! t {
$(
($name) => {
$variant
};
)*
}
};
}
make_t_for_all_tokens! {
"fn" as Token::Fn,
"return" as Token::Return,
"let" as Token::Let,
}
// This creates
//
// macro_rules! t {
// ("fn") => {
// Token::Fn
// };
// ("return") => {
// Token::Return
// };
// ("let") => {
// Token::Let
// };
// }
t!["fn"];
```
### Before
```
error: no rules expected the token `"fn"`
--> src/main.rs:103:10
|
32 | macro_rules! t {
| -------------- when calling this macro
...
103 | t!["fn"];
| ^^^^ no rules expected this token in macro call
|
note: while trying to match `"fn"`
--> src/main.rs:34:6
|
34 | ($name) => {
| ^^^^^
...
58 | / make_t_for_all_tokens! {
59 | | "fn" as Token::Fn,
60 | | "return" as Token::Return,
61 | | "let" as Token::Let,
62 | | }
| |_- in this macro invocation
= note: captured metavariables except for `$tt`, `$ident` and `$lifetime` cannot be compared to other tokens
= note: this error originates in the macro `make_t_for_all_tokens` (in Nightly builds, run with -Z macro-backtrace for more info)
```
### After
```
error: no rules expected the token `"fn"`
--> src/main.rs:103:10
|
32 | macro_rules! t {
| -------------- when calling this macro
...
103 | t!["fn"];
| ^^^^ no rules expected this token in macro call
|
note: while trying to match `"fn"`
--> src/main.rs:34:6
|
34 | ($name) => {
| ^^^^^
...
58 | / make_t_for_all_tokens! {
59 | | "fn" as Token::Fn,
60 | | "return" as Token::Return,
61 | | "let" as Token::Let,
62 | | }
| |_- in this macro invocation
= note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens
= note: see https://doc.rust-lang.org/nightly/reference/macros-by-example.html#forwarding-a-matched-fragment for more information
= help: try using `:tt` instead in the macro definition
= note: this error originates in the macro `make_t_for_all_tokens` (in Nightly builds, run with -Z macro-backtrace for more info)
```
## Unresolved questions
- Preferrably the suggestion should be attached to the `$name:literal` part of the outer macro, instead of being in the notes section at the end. But I'm not familiar with how the compiler works at all, and I have no idea how to approach this kind of solution.
- `@Nilstrieb` raised a question that the suggestion of adding `:tt` isn't accurate when there's more than `tt` being matched, for example when the input is an `item`.
Adds a link to the relevant part of The Rust Reference in the eror
message, and suggests a possible fix (replacing the fragment specifier
with :tt in the macro definition).
Fixes typos in the original message.
Signed-off-by: Lena Milizé <me@lvmn.org>
It partially expands crate attributes before the main expansion pass (without modifying the crate), and the produced preliminary crate attribute list is used for querying a few attributes that are required very early.
Crate-level cfg attributes are then expanded normally during the main expansion pass, like attributes on any other nodes.
This makes it easier to open the messages file while developing on features.
The commit was the result of automatted changes:
for p in compiler/rustc_*; do mv $p/locales/en-US.ftl $p/messages.ftl; rmdir $p/locales; done
for p in compiler/rustc_*; do sed -i "s#\.\./locales/en-US.ftl#../messages.ftl#" $p/src/lib.rs; done
Rollup of 9 pull requests
Successful merges:
- #104363 (Make `unused_allocation` lint against `Box::new` too)
- #106633 (Stabilize `nonzero_min_max`)
- #106844 (allow negative numeric literals in `concat!`)
- #108071 (Implement goal caching with the new solver)
- #108542 (Force parentheses around `match` expression in binary expression)
- #108690 (Place size limits on query keys and values)
- #108708 (Prevent overflow through Arc::downgrade)
- #108739 (Prevent the `start_bx` basic block in codegen from having two `Builder`s at the same time)
- #108806 (Querify register_tools and post-expansion early lints)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Querify register_tools and post-expansion early lints
The 2 extra queries correspond to code that happen before and after macro expansion, and don't need the resolver to exist.
After removing the `map_in_place` method, which isn't much use because
modifying every element in a collection such as a `Vec` can be done
trivially with iteration.