Do not add `;` to expected tokens list when it's wrong
There's a few spots where semicolons are checked for to do error recovery, and should not be suggested (or checked for other stuff).
Fixes#87647
Also add a test case for inserting a semicolon on extern fns.
Without this fix, we got an error like this:
error: expected one of `->`, `where`, or `{`, found `}`
--> chk.rs:3:1
|
2 | fn foo()
| --- - expected one of `->`, `where`, or `{`
| |
| while parsing this `fn`
3 | }
| ^ unexpected token
Since this is inside an extern block, you're required to write function
prototypes with no body. This fixes a regression, and adds a test case
for it.
Improve diagnostic for missing half of binary operator in `if` condition
Fixes#91421. I've also changed it so that it doesn't consume the `else` token in the error case, because it will try to consume it again afterwards, leading to this incorrect error message (where the `else` reported as missing is actually there):
```
error: expected one of `.`, `;`, `?`, `else`, or an operator, found `{`
--> src/main.rs:4:12
|
4 | } else { 4 };
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
```
r? `@lcnr`
expand: Turn `ast::Crate` into a first class expansion target
And stop creating a fake `mod` item for the crate root when expanding a crate, thus addressing FIXMEs left in https://github.com/rust-lang/rust/pull/82238, and making a step towards a proper support for crate-level macro attributes (cc #54726).
I haven't added token collection support for the whole crate in this PR, maybe later.
r? `@Aaron1011`
Tokenize emoji as if they were valid identifiers
In the lexer, consider emojis to be valid identifiers and reject
them later to avoid knock down parse errors.
Partially address #86102.
fix(doctest): detect extern crate items in statement doctests
This partially reverts #91026, because rustdoc needs to detect the extern statements, even when they appear inside implicit `main()`. It does not entirely revert it, so the old bug is still fixed, by duplicating some of the logic from `parse_mod` instead of trying to use it directly.
Fixes#91134
This partially reverts #91026, because rustdoc needs to detect the extern statements,
even when they appear inside implicit `main()`. It does not entirely revert it,
so the old bug is still fixed, by duplicating some of the logic from `parse_mod`
instead of trying to use it directly.
Fixes#91134
TraitKind -> Trait
TyAliasKind -> TyAlias
ImplKind -> Impl
FnKind -> Fn
All `*Kind`s in AST are supposed to be enums.
Tuple structs are converted to braced structs for the types above, and fields are reordered in syntactic order.
Also, mutable AST visitor now correctly visit spans in defaultness, unsafety, impl polarity and constness.
rustc_span: `Ident::invalid` -> `Ident::empty`
The equivalent for `Symbol`s was renamed some time ago (`kw::Invalid` -> `kw::Empty`), and it makes sense to do the same thing for `Ident`s as well.
Nicer error message if the user attempts to do let...else if
Gives a nice "conditional `else if` is not supported for `let...else`" error when encountering a `let...else if` pattern, as suggested in the [let...else tracking issue](https://github.com/rust-lang/rust/issues/87335#issuecomment-944846205).
"Fix" an overflow in byte position math
r? `@estebank`
help! I fixed the ICE only to brick the diagnostic.
I mean, it was wrong previously (using an already expanded macro span), but it is really bad now XD
Rollup of 12 pull requests
Successful merges:
- #88795 (Print a note if a character literal contains a variation selector)
- #89015 (core::ascii::escape_default: reduce struct size)
- #89078 (Cleanup: Remove needless reference in ParentHirIterator)
- #89086 (Stabilize `Iterator::map_while`)
- #89096 ([bootstrap] Improve the error message when `ninja` is not found to link to installation instructions)
- #89113 (dont `.ensure()` the `thir_abstract_const` query call in `mir_build`)
- #89114 (Fixes a technicality regarding the size of C's `char` type)
- #89115 (⬆️ rust-analyzer)
- #89126 (Fix ICE when `indirect_structural_match` is allowed)
- #89141 (Impl `Error` for `FromSecsError` without foreign type)
- #89142 (Fix match for placeholder region)
- #89147 (add case for checking const refs in check_const_value_eq)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Migrate in-tree crates to 2021
This replaces #89075 (cherry picking some of the commits from there), and closes#88637 and fixes#89074.
It excludes a migration of the library crates for now (see tidy diff) because we have some pending bugs around macro spans to fix there.
I instrumented bootstrap during the migration to make sure all crates moved from 2018 to 2021 had the compatibility warnings applied first.
Originally, the intent was to support cargo fix --edition within bootstrap, but this proved fairly difficult to pull off. We'd need to architect the check functionality to support running cargo check and cargo fix within the same x.py invocation, and only resetting sysroots on check. Further, it was found that cargo fix doesn't behave too well with "not quite workspaces", such as Clippy which has several crates. Bootstrap runs with --manifest-path ... for all the tools, and this makes cargo fix only attempt migration for that crate. We can't use e.g. --workspace due to needing to maintain sysroots for different phases of compilation appropriately.
It is recommended to skip the mass migration of Cargo.toml's to 2021 for review purposes; you can also use `git diff d6cd2c6c87 -I'^edition = .20...$'` to ignore the edition = 2018/21 lines in the diff.
Newcomers may write `{1, 2, 3}` for making arrays, and the current error
message is not informative enough to quickly convince them what is
needed to fix the error.
This PR implements a diagnostic for this case, and its output looks like
this:
```text
error: this code is interpreted as a block expression, not an array
--> src/lib.rs:1:22
|
1 | const FOO: [u8; 3] = {
| ______________________^
2 | | 1, 2, 3
3 | | };
| |_^
|
= note: to define an array, one would use square brackets instead of curly braces
help: try using [] instead of {}
|
1 | const FOO: [u8; 3] = [
2 | 1, 2, 3
3 | ];
|
```
Fix#87672
Recover from `Foo(a: 1, b: 2)`
Detect likely `struct` literal using parentheses as delimiters and emit
targeted suggestion instead of type ascription parse error.
Fix#61326.
Revert anon union parsing
Revert PR #84571 and #85515, which implemented anonymous union parsing in a manner that broke the context-sensitivity for the `union` keyword and thus broke stable Rust code.
Fix#88583.
Accept `m!{ .. }.method()` and `m!{ .. }?` statements.
This PR fixes something that I keep running into when using `quote!{}.into()` in a proc macro to convert the `proc_macro2::TokenStream` to a `proc_macro::TokenStream`:
Before:
```
error: expected expression, found `.`
--> src/lib.rs:6:6
|
4 | quote! {
5 | ...
6 | }.into()
| ^ expected expression
```
After:
```
```
(No output, compiles fine.)
---
Context:
For expressions like `{ 1 }` and `if true { 1 } else { 2 }`, we accept them as full statements without a trailing `;`, which means the following is not accepted:
```rust
{ 1 } - 1 // error
```
since that is parsed as two statements: `{ 1 }` and `-1`. Syntactically correct, but the type of `{ 1 }` should be `()` as there is no `;`.
However, for specifically `.` and `?` after the `}`, we do [continue parsing it as an expression](13db8440bb/compiler/rustc_parse/src/parser/expr.rs (L864-L876)):
```rust
{ "abc" }.len(); // ok
```
For braced macro invocations, we do not do this:
```rust
vec![1, 2, 3].len(); // ok
vec!{1, 2, 3}.len(); // error
```
(It parses `vec!{1, 2, 3}` as a full statement, and then complains about `.len()` not being a valid expression.)
This PR changes this to also look for a `.` and `?` after a braced macro invocation. We can be sure the macro is an expression and not a full statement in those cases, since no statement can start with a `.` or `?`.
Use smaller spans for some structured suggestions
Use more accurate suggestion spans for
* argument parse error
* fully qualified path
* missing code block type
* numeric casts
Encode spans relative to the enclosing item
The aim of this PR is to avoid recomputing queries when code is moved without modification.
MCP at https://github.com/rust-lang/compiler-team/issues/443
This is achieved by :
1. storing the HIR owner LocalDefId information inside the span;
2. encoding and decoding spans relative to the enclosing item in the incremental on-disk cache;
3. marking a dependency to the `source_span(LocalDefId)` query when we translate a span from the short (`Span`) representation to its explicit (`SpanData`) representation.
Since all client code uses `Span`, step 3 ensures that all manipulations
of span byte positions actually create the dependency edge between
the caller and the `source_span(LocalDefId)`.
This query return the actual absolute span of the parent item.
As a consequence, any source code motion that changes the absolute byte position of a node will either:
- modify the distance to the parent's beginning, so change the relative span's hash;
- dirty `source_span`, and trigger the incremental recomputation of all code that
depends on the span's absolute byte position.
With this scheme, I believe the dependency tracking to be accurate.
For the moment, the spans are marked during lowering.
I'd rather do this during def-collection,
but the AST MutVisitor is not practical enough just yet.
The only difference is that we attach macro-expanded spans
to their expansion point instead of the macro itself.
Change more x64 size checks to not apply to x32.
Commit 95e096d6 changed a bunch of size checks already, but more have
been added, so this fixes the new ones the same way: the various size
checks that are conditional on target_arch = "x86_64" were not intended
to apply to x86_64-unknown-linux-gnux32, so add
target_pointer_width = "64" to the conditions.
This commit focuses on emitting clean errors for the following syntax
error:
```
Some(42).map(|a|
dbg!(a);
a
);
```
Previous implementation tried to recover after parsing the closure body
(the `dbg` expression) by replacing the next `;` with a `,`, which made
the next expression belong to the next function argument. As such, the
following errors were emitted (among others):
- the semicolon token was not expected,
- a is not in scope,
- Option::map is supposed to take one argument, not two.
This commit allows us to gracefully handle this situation by adding
giving the parser the ability to remember when it has just parsed a
closure body inside a function call. When this happens, we can treat the
unexpected `;` specifically and try to parse as much statements as
possible in order to eat the whole block. When we can't parse statements
anymore, we generate a clean error indicating that the braces are
missing, and return an ExprKind::Err.
This reverts commit 059b68dd67.
Note that this was manually adjusted to retain some of the refactoring
introduced by commit 059b68dd67, so that it could
likewise retain the correction introduced in commit
5b4bc05fa5
Improve diagnostics for unary plus operators (#88276)
This pull request improves the diagnostics emitted on parsing a unary plus operator. See #88276.
Before:
```
error: expected expression, found `+`
--> src/main.rs:2:13
|
2 | let x = +1;
| ^ expected expression
```
After:
```
error: leading `+` is not supported
--> main.rs:2:13
|
2 | let x = +1;
| ^
| |
| unexpected `+`
| help: try removing the `+`
```
Commit 95e096d6 changed a bunch of size checks already, but more have
been added, so this fixes the new ones the same way: the various size
checks that are conditional on target_arch = "x86_64" were not intended
to apply to x86_64-unknown-linux-gnux32, so add
target_pointer_width = "64" to the conditions.
Detect bare blocks with type ascription that were meant to be a `struct` literal
Address part of #34255.
Potential improvement: silence the other knock down errors in `issue-34255-1.rs`.
Point at unclosed delimiters as part of the primary MultiSpan
Both the place where the parser encounters a needed closed delimiter and
the unclosed opening delimiter are important, so they should get the
same level of highlighting in the output.
_Context: https://twitter.com/mwk4/status/1430631546432675840_
Path remapping: Make behavior of diagnostics output dependent on presence of --remap-path-prefix.
This PR fixes a regression (#87745) with `--remap-path-prefix` where the flag stopped causing diagnostic messages to be remapped as well. The regression was introduced in https://github.com/rust-lang/rust/pull/83813 where we erroneously assumed that remapping of diagnostic messages was not desired anymore (because #70642 partially undid that functionality with nobody objecting).
The issue is fixed by making `--remap-path-prefix` remap diagnostic messages again, including for paths that have been remapped in upstream crates (e.g. the standard library). This means that "sysroot-localization" (implemented in #70642) is also disabled if `rustc` is invoked with `--remap-path-prefix`. The assumption is that once someone starts explicitly remapping paths they also don't want paths to their local Rust installation in their build output.
In the future we might want to give more fine-grained control over this behavior via compiler flags (see https://github.com/rust-lang/rfcs/pull/3127 for a related RFC). For now this PR is intended as a regression fix.
This PR is an alternative to https://github.com/rust-lang/rust/pull/88191, which makes diagnostic messages be remapped unconditionally. That approach, however, would effectively revert #70642.
Fixes https://github.com/rust-lang/rust/issues/87745.
cc `@cbeuw`
r? `@ghost`
Introduce `let...else`
Tracking issue: #87335
The trickiest part for me was enforcing the diverging else block with clear diagnostics. Perhaps the obvious solution is to expand to `let _: ! = ..`, but I decided against this because, when a "mismatched type" error is found in typeck, there is no way to trace where in the HIR the expected type originated, AFAICT. In order to pass down this information, I believe we should introduce `Expectation::LetElseNever(HirId)` or maybe add `HirId` to `Expectation::HasType`, but I left that as a future enhancement. For now, I simply assert that the block is `!` with a custom `ObligationCauseCode`, and I think this is clear enough, at least to start. The downside here is that the error points at the entire block rather than the specific expression with the wrong type. I left a todo to this effect.
Overall, I believe this PR is feature-complete with regard to the RFC.
Old error output:
3 | let _: usize = $f;
| ----- ^ expected `usize`, found struct `Baz`
| |
| expected due to this
New error output:
3 | let _: usize = $f;
| ----- ^^ expected `usize`, found struct `Baz`
| |
| expected due to this
Old error output:
= note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
help: wrap this expression in parentheses
|
4 | break '_l $f(;)
| ^ ^
New error output:
= note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
help: wrap this expression in parentheses
|
4 | break '_l ($f);
| ^ ^
Both the place where the parser encounters a needed closed delimiter and
the unclosed opening delimiter are important, so they should get the
same level of highlighting in the output.
- [x] Removed `?const` and change uses of `?const`
- [x] Added `~const` to the AST. It is gated behind const_trait_impl.
- [x] Validate `~const` in ast_validation.
- [ ] Add enum `BoundConstness` to the HIR. (With variants `NotConst` and
`ConstIfConst` allowing future extensions)
- [ ] Adjust trait selection and pre-existing code to use `BoundConstness`.
- [ ] Optional steps (*for this PR, obviously*)
- [ ] Fix#88155
- [ ] Do something with constness bounds in chalk
Remove `Session.used_attrs` and move logic to `CheckAttrVisitor`
Instead of updating global state to mark attributes as used,
we now explicitly emit a warning when an attribute is used in
an unsupported position. As a side effect, we are to emit more
detailed warning messages (instead of just a generic "unused" message).
`Session.check_name` is removed, since its only purpose was to mark
the attribute as used. All of the callers are modified to use
`Attribute.has_name`
Additionally, `AttributeType::AssumedUsed` is removed - an 'assumed
used' attribute is implemented by simply not performing any checks
in `CheckAttrVisitor` for a particular attribute.
We no longer emit unused attribute warnings for the `#[rustc_dummy]`
attribute - it's an internal attribute used for tests, so it doesn't
mark sense to treat it as 'unused'.
With this commit, a large source of global untracked state is removed.
Instead of updating global state to mark attributes as used,
we now explicitly emit a warning when an attribute is used in
an unsupported position. As a side effect, we are to emit more
detailed warning messages (instead of just a generic "unused" message).
`Session.check_name` is removed, since its only purpose was to mark
the attribute as used. All of the callers are modified to use
`Attribute.has_name`
Additionally, `AttributeType::AssumedUsed` is removed - an 'assumed
used' attribute is implemented by simply not performing any checks
in `CheckAttrVisitor` for a particular attribute.
We no longer emit unused attribute warnings for the `#[rustc_dummy]`
attribute - it's an internal attribute used for tests, so it doesn't
mark sense to treat it as 'unused'.
With this commit, a large source of global untracked state is removed.
Allow labeled loops as value expressions for `break`
Fixes#86948. This is currently allowed:
```rust
return 'label: loop { break 'label 42; };
break ('label: loop { break 'label 42; });
break 1 + 'label: loop { break 'label 42; };
break 'outer 'inner: loop { break 'inner 42; };
```
But not this:
```rust
break 'label: loop { break 'label 42; };
```
I have fixed this, so that the above now parses as an unlabeled break with a labeled loop as its value expression.
Fix a parser ICE on invalid `fn` body
Fixes#87635
A better fix would add a check for `fn` body on `expected_one_of_not_found` but I haven't come up with a graceful way. Any idea?
r? ```@oli-obk``` ```@estebank```
After this commit, `unsafe async fn ...` now suggests the `async unsafe` fix
instead of misunderstanding the issue.
This is not perfect for repeated keywords (`const async const`) and for
keywords that are misplaced after `extern "some abi"` because of the way
`check_fn_font_matter` works, but changing it breaks so many tests and
diagnostics it has been judged too high a cost for this 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.
Suggest `br` if the unknown string prefix `rb` is found
Currently, for the following code:
```rust
fn main() {
rb"abc";
}
```
we issue the following suggestion:
```
help: consider inserting whitespace here
|
2 | rb "abc";
| --
```
With my changes (only in edition 2021, where unknown prefixes became an error), I get:
```
help: use `br` for a raw byte string
|
2 | br"abc";
| ^^
```
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.
Add diagnostics for mistyped inclusive range
Inclusive ranges are correctly typed as `..=`. However, it's quite easy to think of it as being like `==`, and type `..==` instead. This PR adds helpful diagnostics for this case.
Resolves#86395 (there are some other cases there, but I think those should probably have separate issues).
r? `@estebank`
Stabilize "RangeFrom" patterns in 1.55
Implements a partial stabilization of #67264 and #37854.
Reference PR: https://github.com/rust-lang/reference/pull/900
# Stabilization Report
This stabilizes the `X..` pattern, shown as such, offering an exhaustive match for unsigned integers:
```rust
match x as u32 {
0 => println!("zero!"),
1.. => println!("positive number!"),
}
```
Currently if a Rust author wants to write such a match on an integer, they must use `1..={integer}::MAX` . By allowing a "RangeFrom" style pattern, this simplifies the match to not require the MAX path and thus not require specifically repeating the type inside the match, allowing for easier refactoring. This is particularly useful for instances like the above case, where different behavior on "0" vs. "1 or any positive number" is desired, and the actual MAX is unimportant.
Notably, this excepts slice patterns which include half-open ranges from stabilization, as the wisdom of those is still subject to some debate.
## Practical Applications
Instances of this specific usage have appeared in the compiler:
16143d1067/compiler/rustc_middle/src/ty/inhabitedness/mod.rs (L219)673d0db5e3/compiler/rustc_ty_utils/src/ty.rs (L524)
And I have noticed there are also a handful of "in the wild" users who have deployed it to similar effect, especially in the case of rejecting any value of a certain number or greater. It simply makes it much more ergonomic to write an irrefutable match, as done in Katholieke Universiteit Leuven's [SCALE and MAMBA project](05e5db00d5/WebAssembly/scale_std/src/fixed_point.rs (L685-L695)).
## Tests
There were already many tests in [src/test/ui/half-open-range/patterns](90a2e5e3fe/src/test/ui/half-open-range-patterns), as well as [generic pattern tests that test the `exclusive_range_pattern` feature](673d0db5e3/src/test/ui/pattern/usefulness/integer-ranges/reachability.rs), many dating back to the feature's introduction and remaining standing to this day. However, this stabilization comes with some additional tests to explore the... sometimes interesting behavior of interactions with other patterns. e.g. There is, at least, a mild diagnostic improvement in some edge cases, because before now, the pattern `0..=(5+1)` encounters the `half_open_range_patterns` feature gate and can thus emit the request to enable the feature flag, while also emitting the "inclusive range with no end" diagnostic. There is no intent to allow an `X..=` pattern that I am aware of, so removing the flag request is a strict improvement. The arrival of the `J | K` "or" pattern also enables some odd formations.
Some of the behavior tested for here is derived from experiments in this [Playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=58777b3c715c85165ac4a70d93efeefc) example, linked at https://github.com/rust-lang/rust/issues/67264#issuecomment-812770692, which may be useful to reference to observe the current behavior more closely.
In addition tests constituting an explanation of the "slicing range patterns" syntax issue are included in this PR.
## Desiderata
The exclusive range patterns and half-open range patterns are fairly strongly requested by many authors, as they make some patterns much more natural to write, but there is disagreement regarding the "closed" exclusive range pattern or the "RangeTo" pattern, especially where it creates "off by one" gaps in the presence of a "catch-all" wildcard case. Also, there are obviously no range analyses in place that will force diagnostics for e.g. highly overlapping matches. I believe these should be warned on, ideally, and I think it would be reasonable to consider such a blocker to stabilizing this feature, but there is no technical issue with the feature as-is from the purely syntactic perspective as such overlapping or missed matches can already be generated today with such a catch-all case. And part of the "point" of the feature, at least from my view, is to make it easier to omit wildcard matches: a pattern with such an "open" match produces an irrefutable match and does not need the wild card case, making it easier to benefit from exhaustiveness checking.
## History
- Implemented:
- Partially via exclusive ranges: https://github.com/rust-lang/rust/pull/35712
- Fully with half-open ranges: https://github.com/rust-lang/rust/pull/67258
- Unresolved Questions:
- The precedence concerns of https://github.com/rust-lang/rust/pull/48501 were considered as likely requiring adjustment but probably wanting a uniform consistent change across all pattern styles, given https://github.com/rust-lang/rust/issues/67264#issuecomment-720711656, but it is still unknown what changes might be desired
- How we want to handle slice patterns in ranges seems to be an open question still, as witnessed in the discussion of this PR!
I checked but I couldn't actually find an RFC for this, and given "approved provisionally by lang team without an RFC", I believe this might require an RFC before it can land? Unsure of procedure here, on account of this being stabilizing a subset of a feature of syntax.
r? `@scottmcm`
Fix ICE when misplaced visibility cannot be properly parsed
Fixes#86895
The issue was that a failure to parse the visibility was causing the original error to be dropped before being emitted.
The resulting error isn't quite as nice as when the visibility is parsed properly, but I'm not sure which error to prioritize here. Displaying both errors might be too confusing.
r? ```@estebank```
Recover from `&dyn mut ...` parse errors
Consider this example:
```rust
fn main() {
let r: &dyn mut Trait;
}
```
This currently leads to:
```
error: expected one of `!`, `(`, `;`, `=`, `?`, `for`, lifetime, or path, found keyword `mut`
--> src/main.rs:2:17
|
2 | let r: &dyn mut Trait;
| ^^^ expected one of 8 possible tokens
error: aborting due to previous error
```
However, especially for beginners, I think it is easy to get `&dyn mut` and `&mut dyn` confused. With my changes, I get a help message, and the parser even recovers:
```
error: `mut` must precede `dyn`
--> test.rs:2:12
|
2 | let r: &dyn mut Trait;
| ^^^^^^^^ help: place `mut` before `dyn`: `&mut dyn`
error[E0405]: cannot find trait `Trait` in this scope
--> test.rs:2:21
|
2 | let r: &dyn mut Trait;
| ^^^^^ not found in this scope
error: aborting due to 2 previous errors
```
Remove unused dependencies from compiler crates
Various compiler crates have dependencies that they don't appear to use. I used some scripting to detect such dependencies, filtered them based on some manual review, and removed those that do indeed appear to be entirely unused.
Use HTTPS links where possible
While looking at #86583, I wondered how many other (insecure) HTTP links were in `rustc`. This changes most other `http` links to `https`. While most of the links are in comments or documentation, there are a few other HTTP links that are used by CI that are changed to HTTPS.
Notes:
- I didn't change any to or in licences
- Some links don't support HTTPS :(
- Some `http` links were dead, in those cases I upgraded them to their new places (all of which used HTTPS)
Re-add support for parsing (and pretty-printing) inner-attributes in match body
Re-add support for parsing (and pretty-printing) inner-attributes within body of a `match`.
In other words, we can do `match EXPR { #![inner_attr] ARM_1 ARM_2 ... }` again.
I believe this unbreaks the only four crates that crater flagged as broken by PR #83312.
(I am putting this up so that the lang-team can check it out and decide whether it changes their mind about what to do regarding PR #83312.)
Fix two ICEs in the parser
This pull request fixes#84104 and fixes#84148. The latter is caused by an invalid `assert_ne!()` in the parser, which I have simply removed because the error is then caught in another part of the parser.
#84104 is somewhat more subtle and has to do with a suggestion to remove extraneous `<` characters; for instance:
```rust
fn main() {
foo::<Ty<<<i32>();
}
```
currently leads to
```
error: unmatched angle brackets
--> unmatched-langle.rs:2:10
|
2 | foo::<Ty<<<i32>();
| ^^^ help: remove extra angle brackets
```
which is obviously wrong and stems from the fact that the code for issuing the above suggestion does not consider the possibility that there might be other tokens in between the opening angle brackets. In #84104, this has led to a span being generated that ends in the middle of a multi-byte character (because the code issuing the suggestion thought that it was only skipping over `<`, which are single-byte), causing an ICE.
Remove unused feature gates
The first commit removes a usage of a feature gate, but I don't expect it to be controversial as the feature gate was only used to workaround a limitation of rust in the past. (closures never being `Clone`)
The second commit uses `#[allow_internal_unstable]` to avoid leaking the `trusted_step` feature gate usage from inside the index newtype macro. It didn't work for the `min_specialization` feature gate though.
The third commit removes (almost) all feature gates from the compiler that weren't used anyway.
# Stabilization report
## Summary
This stabilizes using macro expansion in key-value attributes, like so:
```rust
#[doc = include_str!("my_doc.md")]
struct S;
#[path = concat!(env!("OUT_DIR"), "/generated.rs")]
mod m;
```
See the changes to the reference for details on what macros are allowed;
see Petrochenkov's excellent blog post [on internals](https://internals.rust-lang.org/t/macro-expansion-points-in-attributes/11455)
for alternatives that were considered and rejected ("why accept no more
and no less?")
This has been available on nightly since 1.50 with no major issues.
## Notes
### Accepted syntax
The parser accepts arbitrary Rust expressions in this position, but any expression other than a macro invocation will ultimately lead to an error because it is not expected by the built-in expression forms (e.g., `#[doc]`). Note that decorators and the like may be able to observe other expression forms.
### Expansion ordering
Expansion of macro expressions in "inert" attributes occurs after decorators have executed, analogously to macro expressions appearing in the function body or other parts of decorator input.
There is currently no way for decorators to accept macros in key-value position if macro expansion must be performed before the decorator executes (if the macro can simply be copied into the output for later expansion, that can work).
## Test cases
- https://github.com/rust-lang/rust/blob/master/src/test/ui/attributes/key-value-expansion-on-mac.rs
- https://github.com/rust-lang/rust/blob/master/src/test/rustdoc/external-doc.rs
The feature has also been dogfooded extensively in the compiler and
standard library:
- https://github.com/rust-lang/rust/pull/83329
- https://github.com/rust-lang/rust/pull/83230
- https://github.com/rust-lang/rust/pull/82641
- https://github.com/rust-lang/rust/pull/80534
## Implementation history
- Initial proposal: https://github.com/rust-lang/rust/issues/55414#issuecomment-554005412
- Experiment to see how much code it would break: https://github.com/rust-lang/rust/pull/67121
- Preliminary work to restrict expansion that would conflict with this
feature: https://github.com/rust-lang/rust/pull/77271
- Initial implementation: https://github.com/rust-lang/rust/pull/78837
- Fix for an ICE: https://github.com/rust-lang/rust/pull/80563
## Unresolved Questions
~~https://github.com/rust-lang/rust/pull/83366#issuecomment-805180738 listed some concerns, but they have been resolved as of this final report.~~
## Additional Information
There are two workarounds that have a similar effect for `#[doc]`
attributes on nightly. One is to emulate this behavior by using a limited version of this feature that was stabilized for historical reasons:
```rust
macro_rules! forward_inner_docs {
($e:expr => $i:item) => {
#[doc = $e]
$i
};
}
forward_inner_docs!(include_str!("lib.rs") => struct S {});
```
This also works for other attributes (like `#[path = concat!(...)]`).
The other is to use `doc(include)`:
```rust
#![feature(external_doc)]
#[doc(include = "lib.rs")]
struct S {}
```
The first works, but is non-trivial for people to discover, and
difficult to read and maintain. The second is a strange special-case for
a particular use of the macro. This generalizes it to work for any use
case, not just including files.
I plan to remove `doc(include)` when this is stabilized. The
`forward_inner_docs` workaround will still compile without warnings, but
I expect it to be used less once it's no longer necessary.
Recover from invalid `struct` item syntax
Parse unsupported "default field const values":
```rust
struct S {
field: Type = const_val,
}
```
Recover from small `:` typo and provide suggestion:
```rust
struct S {
field; Type,
field2= Type,
}
```
Fix `--remap-path-prefix` not correctly remapping `rust-src` component paths and unify handling of path mapping with virtualized paths
This PR fixes#73167 ("Binaries end up containing path to the rust-src component despite `--remap-path-prefix`") by preventing real local filesystem paths from reaching compilation output if the path is supposed to be remapped.
`RealFileName::Named` introduced in #72767 is now renamed as `LocalPath`, because this variant wraps a (most likely) valid local filesystem path.
`RealFileName::Devirtualized` is renamed as `Remapped` to be used for remapped path from a real path via `--remap-path-prefix` argument, as well as real path inferred from a virtualized (during compiler bootstrapping) `/rustc/...` path. The `local_path` field is now an `Option<PathBuf>`, as it will be set to `None` before serialisation, so it never reaches any build output. Attempting to serialise a non-`None` `local_path` will cause an assertion faliure.
When a path is remapped, a `RealFileName::Remapped` variant is created. The original path is preserved in `local_path` field and the remapped path is saved in `virtual_name` field. Previously, the `local_path` is directly modified which goes against its purpose of "suitable for reading from the file system on the local host".
`rustc_span::SourceFile`'s fields `unmapped_path` (introduced by #44940) and `name_was_remapped` (introduced by #41508 when `--remap-path-prefix` feature originally added) are removed, as these two pieces of information can be inferred from the `name` field: if it's anything other than a `FileName::Real(_)`, or if it is a `FileName::Real(RealFileName::LocalPath(_))`, then clearly `name_was_remapped` would've been false and `unmapped_path` would've been `None`. If it is a `FileName::Real(RealFileName::Remapped{local_path, virtual_name})`, then `name_was_remapped` would've been true and `unmapped_path` would've been `Some(local_path)`.
cc `@eddyb` who implemented `/rustc/...` path devirtualisation
Parse unsupported "default field const values":
```rust
struct S {
field: Type = const_val,
}
```
Recover from small `:` typo and provide suggestion:
```rust
struct S {
field; Type,
field2= Type,
}
```
In other words, we can do `match EXPR { #![inner_attr] ARM_1 ARM_2 ... }` again.
I believe this unbreaks the only four crates that crater flagged as broken by PR 83312.
(I am putting this up so that the lang-team can check it out and decide whether
it changes their mind about what to do regarding PR 83312.)
Improve diagnostics for functions in `struct` definitions
Tries to implement #76421.
This is probably going to need unit tests, but I wanted to hear from review all the cases tests should cover.
I'd like to follow up with the "mechanically applicable suggestion here that adds an impl block" step, but I'd need guidance. My idea for now would be to try to parse a function, and if that succeeds, create a dummy `ast::Item` impl block to then format it using `pprust`. Would that be a viable approach? Is there a better alternative?
r? `@matklad` cc `@estebank`