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 `?`.
Const drop
The changes are pretty primitive at this point. But at least it works. ^-^
Problems with the current change that I can think of now:
- [x] `~const Drop` shouldn't change anything in the non-const world.
- [x] types that do not have drop glues shouldn't fail to satisfy `~const Drop` in const contexts. `struct S { a: u8, b: u16 }` This might not fail for `needs_non_const_drop`, but it will fail in `rustc_trait_selection`.
- [x] The current change accepts types that have `const Drop` impls but have non-const `Drop` glue.
Fixes#88424.
Significant Changes:
- `~const Drop` is no longer treated as a normal trait bound. In non-const contexts, this bound has no effect, but in const contexts, this restricts the input type and all of its transitive fields to either a) have a `const Drop` impl or b) can be trivially dropped (i.e. no drop glue)
- `T: ~const Drop` will not be linted like `T: Drop`.
- Instead of recursing and iterating through the type in `rustc_mir::transform::check_consts`, we use the trait system to special case `~const Drop`. See [`rustc_trait_selection::...::candidate_assembly#assemble_const_drop_candidates`](https://github.com/fee1-dead/rust/blob/const-drop/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs#L817) and others.
Changes not related to `const Drop`ping and/or changes that are insignificant:
- `Node.constness_for_typeck` no longer returns `hir::Constness::Const` for type aliases in traits. This was previously used to hack how we determine default bound constness for items. But because we now use an explicit opt-in, it is no longer needed.
- Removed `is_const_impl_raw` query. We have `impl_constness`, and the only existing use of that query uses `HirId`, which means we can just operate it with hir.
- `ty::Destructor` now has a field `constness`, which represents the constness of the destructor.
r? `@oli-obk`
Enum should prefer discriminant zero for niche
Given an enum with unassigned zero-discriminant, rust should prefer it for niche selection.
Zero as discriminant for `Option<Enum>` makes it possible for LLVM to optimize resulting asm.
- Eliminate branch when expected value coincides.
- Use smaller instruction `test eax, eax` instead of `cmp eax, ?`
- Possible interaction with zeroed memory?
Example:
```rust
pub enum Size {
One = 1,
Two = 2,
Three = 3,
}
pub fn handle(x: Option<Size>) -> u8 {
match x {
None => {0}
Some(size) => {size as u8}
}
}
```
In this case discriminant zero is available as a niche.
Above example on nightly:
```asm
mov eax, edi
cmp al, 4
jne .LBB0_2
xor eax, eax
.LBB0_2:
ret
```
PR:
```asm
mov eax, edi
ret
```
I created this PR because I had a performance regression when I tried to use an enum to represent legal grapheme byte-length for utf8.
Using an enum instead of `NonZeroU8` [here](d683304f5d/src/internal/decoder_incomplete.rs (L90))
resulted in a performance regression of about 5%.
I consider this to be a somewhat realistic benchmark.
Thanks to `@ogoffart` for pointing me in the right direction!
Edit: Updated description
Improve error message for missing trait in trait impl
Fixes#88818. For the following example:
```rust
struct S { }
impl for S { }
```
the current output is:
```
error: missing trait in a trait impl
--> t1.rs:2:5
|
2 | impl for S { }
| ^
```
With my changes, I get:
```
error: missing trait in a trait impl
--> t1.rs:2:5
|
2 | impl for S { }
| ^
|
help: add a trait here
|
2 | impl Trait for S { }
| +++++
help: for an inherent impl, drop this `for`
|
2 - impl for S { }
2 + impl S { }
|
```
Fix duplicate bounds for const_trait_impl
Fixes#88383.
Compare the constness of the candidates before winnowing and removing a `~const` `BoundCandidate`.
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
generic_const_exprs: use thir for abstract consts instead of mir
Changes `AbstractConst` building to use `thir` instead of `mir` so that there's less chance of consts unifying when they shouldn't because lowering to mir dropped information (see `abstract-consts-as-cast-5.rs` test)
r? `@lcnr`
Detect stricter constraints on gats where clauses in impls vs trait
I might try to see if I can do a bit more to improve these diagnostics, but any initial feedback is appreciated. I can also do any additional work in a followup PR.
r? `@estebank`
Fix ICE for functions with more than 65535 arguments
This pull request fixes#88577 by changing the `param_idx` field in the `Param` variant of `WellFormedLoc` from `u16` to `u32`, thus allowing for more than 65,535 arguments in a function. Note that I also added a regression test, but needed to add `// ignore-tidy-filelength` because the test is more than 8000 lines long.
Fix non-capturing closure return type coercion
Fixes#88097. For the example given there:
```rust
fn peculiar() -> impl Fn(u8) -> u8 {
return |x| x + 1
}
```
which incorrectly reports an error, I noticed something weird in the debug log:
```
DEBUG rustc_typeck::check::coercion coercion::try_find_coercion_lub([closure@test.rs:2:12: 2:21], [closure@test.rs:2:12: 2:21], exprs=1 exprs)
```
Apparently, `try_find_coercion_lub()` thinks that the LUB for two closure types always has to be a function pointer (which explains the `expected closure, found fn pointer` error in #88097). There is one corner case where that isn't true, though — namely, when the two closure types are equal, in which case the trivial LUB is the type itself. This PR fixes this by inserting an explicit check for type equality in `try_find_coercion_lub()`.
rustc: use more correct span data in for loop desugaring
Fixes#82462
Before:
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
LL | for x in DroppingSlice(&*v).iter(); {
| +
After:
help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
|
LL | };
| +
This seems like a reasonable fix: since the desugared "expr_drop_temps_mut" contains the entire desugared loop construct, its span should contain the entire loop construct as well.
Emit proper errors when on missing closure braces
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.
Closes#88065.
r? `@estebank`
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
Add a regression test for #88649
I noticed that #88649 does not have a regression test, so I add one in this PR.
The test fails with this without #88678:
```
error[E0080]: evaluation of constant value failed
--> /checkout/src/test/ui/consts/issue-88649.rs:13:52
|
LL | Foo::Variant1(x) | Foo::Variant2(x) if x => {}
| ^ StorageLive on a local that was already live
error: aborting due to previous error
For more information about this error, try `rustc --explain E0080`.
```
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 `+`
```