Desugar async blocks in HIR instead of MIR#157309
Conversation
Debug-printing MIR is not readable. We have dedicated infra to dump MIR, use it. Added benefit, this avoid hardcoding that `AddMovesForPackedDrops` is the first pass in make_shim (it is not).
Closures, coroutines, coroutine witnesses and coroutine closures use the same syntax. This used to be copy-paste but gradually departed.
This comment has been minimized.
This comment has been minimized.
|
cc @Swatinem as you have done work on this in the past |
3aee865 to
d17eeb1
Compare
|
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Desugar async blocks in HIR instead of MIR
|
The job Click to see the possible cause of the failure (guessed by this bot) |
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (ec00386): comparison URL. Overall result: ❌✅ regressions and improvements - please read:Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf. Next, please: If you can, justify the regressions found in this try perf run in writing along with @bors rollup=never Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary -0.2%, secondary 0.9%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (secondary 6.3%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeResults (primary 0.1%, secondary 6.4%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Bootstrap: 510.698s -> 509.663s (-0.20%) |
| --> $DIR/issue-76168-hr-outlives-3.rs:13:1 | ||
| | | ||
| LL | / { | ||
| LL | | | ||
| LL | | | ||
| LL | | let mut i = 41; | ||
| LL | | &mut i; | ||
| LL | | } | ||
| | |_^ expected an `FnOnce(&'a mut i32)` closure, found `i32` | ||
| | | ||
| = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32` |
There was a problem hiding this comment.
Not sure why the later error isn't marked as duplicate automatically. I don't see any visual difference between the two. It'd be a shame to start producing redundant errors here. (but so far things look reasonable in general.)
| error[E0038]: the trait `Foo` is not dyn compatible | ||
| --> $DIR/inference_var_self_argument.rs:5:33 | ||
| --> $DIR/inference_var_self_argument.rs:5:34 | ||
| | | ||
| LL | async fn foo(self: &dyn Foo) { | ||
| | ^ `Foo` is not dyn compatible | ||
| LL | async fn foo(self: &dyn Foo) { | ||
| | __________________________________^ | ||
| LL | | | ||
| LL | | | ||
| LL | | todo!() | ||
| LL | | } | ||
| | |_____^ `Foo` is not dyn compatible |
There was a problem hiding this comment.
We should have a better span (ideally pointing at dyn Foo). Errors that point at the whole body are bad when presenting information in IDEs, as then you end up with a whole lot of text with a red underline, generally masking other errors.
| = note: no two async blocks, even if identical, have the same type | ||
| = help: consider pinning your async block and casting it to a trait object |
There was a problem hiding this comment.
These two are redundant with the ones immediately above.
| | ----- ^^^^^^^^ | ||
| | | | | ||
| | | expected `async` block, found a different `async` block | ||
| | | arguments to this function are incorrect |
There was a problem hiding this comment.
We need to customize the E0308 logic for function calls to account for this new desugaring, as talking about "arguments to this function" when pointing at an async block are less than ideal. Just not including the label would be enough., but ideally we'd make the previous output whihch points at fun still work even with the additional level of indirection.
There was a problem hiding this comment.
Ideally we'd point at the tail expression at least, instead of the whole block.
There was a problem hiding this comment.
This is a problem: we are no longer pointing at user code in the recursion error. There's no way a normal user can figure out what caused there to be a problem with the new output.
Implements MCP rust-lang/compiler-team#997
Based on #157166
In the current implementation,
gen/async/async genblocks and closures have typeCoroutine(..)andCoroutineClosure(..). Those types implementIterator,FutureorAsyncIteratordepending on the initial desugaring.This creates a lot of complexity:
I propose to change the desugaring for coroutines to:
gen { .. }becomesCoroutineIterator::from_coroutine(#[coroutine] { .. });async { .. }becomesCoroutineFuture::from_coroutine(#[coroutine] { .. });async gen { .. }becomesCoroutineAsyncIterator::from_coroutine(#[coroutine] { .. }).This way, all coroutines implement
std::ops::Coroutineandcoreis responsible for translating this to user-friendly traits. All the complexity is pushed to error-reporting code, which is not soundness-critical.Coroutine closures are a little more complex, as we need to keep the
CoroutineClosuretype for borrow-checking.Main design point: I create two methods on
TyCtxtthat are meant to do the back-and-forth between wrapped and unwrapped coroutines.coroutine_desugared_typewraps a coroutine inside the adapter struct.try_unwrap_desugared_coroutineunwraps it.r? @oli-obk
cc @lcnr @RalfJung
cc @estebank as I modify quite a lot of diagnostic code