record fewer adjustment types in generator witnesses, avoid spurious drops in MIR construction
Don't record all intermediate adjustment types -- That's way more than is needed, and winds up recording types that will never appear in MIR.
Note: I'm like 90% sure that this logic is correct, but this stuff is subtle and can be hard to keep straight. However, the risk of this PR is fairly low -- if we miss types here, I believe the most common outcome is an ICE.
This fixes the original issue cited by #64477, but I'm leaving the issue open for now since there may be other cases we can detect and improve in a targeted way.
r? @Zoxc
Currently, after a CALL terminator is created in MIR, we insert DROP
statements for all of its operands -- even though they were just moved
shortly before! These spurious drops are later removed, but not before
causing borrow check errors.
This PR series modifies the drop code to track operands that were
moved and avoid creating drops for them.
Right now, I'm only using this mechanism for calls, but it seems
likely it could be used in more places.
Polonius: more `ui` test suite fixes
Since #62736, new tests have been added, and the `run-pass` suite was merged into the `ui` suite.
This PR adds the missing tests expectations for Polonius, and updates the existing ones where the NLL output has changed in some manner (e.g. ordering of notes)
Those are the trivial cases, but a more-detailed explanation is available [in this write-up](https://hackmd.io/CjYB0fs4Q9CweyeTdKWyEg?both#26-async-awaitasync-borrowck-escaping-closure-errorrs-outputs-from-NLL-Polonius-diff) starting at test case 26: they are only differing in diagnostics and instances of other existing test cases differences.
Only 3 of the 9020 tests are still "failing" at the moment (1 failure, 2 OOMs).
r? @nikomatsakis
This commit changes the HIR lowering around `await` so that temporary
lifetimes are extended. Previously, await was lowered as:
```rust
{
let mut pinned = future;
loop {
match ::std::future::poll_with_tls_context(unsafe {
<::std::pin::Pin>::new_unchecked(&mut pinned)
}) {
::std::task::Poll::Ready(result) => break result,
::std::task::Poll::Pending => {}
}
yield ();
}
}
```
With this commit, await is lowered as:
```rust
match future {
mut pinned => loop {
match ::std::future::poll_with_tls_context(unsafe {
<::std::pin::Pin>::new_unchecked(&mut pinned)
}) {
::std::task::Poll::Ready(result) => break result,
::std::task::Poll::Pending => {}
}
yield ();
}
}
```
However, this change has the following side-effects:
- All temporaries in future will be considered to live across a
yield for the purpose of auto-traits.
- Borrowed temporaries in future are likely to be considered to be live
across the yield for the purpose of the generator transform.
Signed-off-by: David Wood <david@davidtw.co>
Fix suggestion from incorrect `move async` to `async move`.
PR for #61920. Happy with the test. There must be a better implementation though - possibly a MIR visitor to estabilsh a span that doesn't include the `async` keyword?
Object-lifetime-default elision is distinct from other forms of
elision; it always refers to some enclosing lifetime *present in the
surrounding type* (e.g., `&dyn Bar` expands to `&'a (dyn Bar + 'a)`.
If there is no enclosing lifetime, then it expands to `'static`.
Therefore, in an `impl Trait<Item = dyn Bar>` setting, we don't expand
to create a lifetime parameter for the `dyn Bar + 'X` bound. It will
just be resolved to `'static`.
Annoyingly, the responsibility for this resolution is spread across
multiple bits of code right now (`middle::resolve_lifetimes`,
`lowering`). The lowering code knows that the default is for an object
lifetime, but it doesn't know what the correct result would be.
Probably this should be fixed, but what we do now is a surgical fix:
we have it generate a different result for elided lifetimes in a
object context, and then we can ignore those results when figuring out
the lifetimes that are captured in the opaque type.
Suggest Rust 2018 on `<expr>.await` with no such field
When type checking a field projection (`fn check_field`) to `<expr>.await` where `<expr>: τ` and `τ` is not a primitive type, suggest switching to Rust 2018. E.g.
```
error[E0609]: no field `await` on type `std::pin::Pin<&mut dyn std::future::Future<Output = ()>>`
--> $DIR/suggest-switching-edition-on-await.rs:31:7
|
LL | x.await;
| ^^^^^ unknown field
|
= note: to `.await` a `Future`, switch to Rust 2018
= help: set `edition = "2018"` in `Cargo.toml`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide
```
Fixes https://github.com/rust-lang/rust/issues/63533
This PR also performs some preparatory cleanups in `fn check_field`; the last 2 commits are where the suggestion is introduced and tested respectively.
r? @varkor
handle elision in async fn correctly
We now always make fresh lifetimne parameters for all elided
lifetimes, whether they are in the inputs or outputs. But then
we generate `'_` in the case of elided lifetimes from the outputs.
Example:
```rust
async fn foo<'a>(x: &'a u32) -> &u32 { .. }
```
becomes
```rust
type Foo<'a, 'b> = impl Future<Output = &'b u32>;
fn foo<'a>(x: &'a u32) -> Foo<'a, '_>
```
Fixes#63388
We now always make fresh lifetimne parameters for all elided
lifetimes, whether they are in the inputs or outputs. But then
we generate `'_` in the case of elided lifetimes from the outputs.
Example:
```rust
async fn foo<'a>(x: &'a u32) -> &u32 { .. }
```
becomes
```rust
type Foo<'a, 'b> = impl Future<Output = &'b u32>;
fn foo<'a>(x: &'a u32) -> Foo<'a, '_>
```
This commit prohibits return position `impl Trait` types that "inherit
lifetimes" from the parent scope. The intent is to forbid cases that are
challenging until they can be addressed properly.
Test interaction between `async { ... }` and `?`, `return`, and `break`
Per the second checkbox in https://github.com/rust-lang/rust/issues/62121#issuecomment-506884048, test that `async { .. }` blocks:
1. do not allow `break` expressions.
2. get targeted by `return` and not the parent function.
3. get targeted by `?` and not the parent function.
Works towards resolving blockers in #63209.
r? @cramertj
Test conditional initialization validation in async fns
r? @cramertj
Per [paper doc](https://paper.dropbox.com/doc/async.await-Call-for-Tests--AiWF2Nt8tgDiA70qFI~oiLOOAg-nMyZGrra7dz9KcFRMLKJy) calling for async/.await tests, tests are desired for conditionally initialized local variables. This PR hopes to provide tests for that.
#63294 seems to be tracking the items from the paper doc that this PR is related to
#62121 is an open issue asking for more async/.await tests that this relates to
---
👍 executed 2 new tests
👍 tidy