Open
Description
Rebinding a value within an async function can cause the generated future to require twice the memory for the value. This seems to only happen if the value was borrowed earlier:
use std::mem;
async fn foo() {
let x = [0u8; 100];
async {}.await;
println!("{}", x.len());
}
async fn a() {
let fut = foo();
let fut = fut;
fut.await;
}
async fn b() {
let fut = foo();
println!("{}", mem::size_of_val(&fut));
let fut = fut;
fut.await;
}
fn main() {
assert_eq!(mem::size_of_val(&foo()), 102);
// 1 + sizeof(foo)
assert_eq!(mem::size_of_val(&a()), 103);
// 1 + (sizeof(foo) * 2)
assert_eq!(mem::size_of_val(&b()), 205);
}
I don't know if this counts as a bug but the behavior is a bit surprising.
The effect is present in both debug and release modes with rustc 1.60.0.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
On deck
Activity
eholk commentedon Apr 15, 2022
@rustbot label A-async-await AsyncAwait-Polish
tmandry commentedon Apr 22, 2022
Hi! This looks related to #62321 and #61849 but not exactly the same as either of those. It might be easier to solve.
eholk commentedon Apr 25, 2022
We discussed this in triage today. It seems like the issue is probably that
MaybeBorrowedLocals
is being too conservative. Once it finds a borrowed local, it stays live until it finds aStorageDead
instruction, and these get inserted at the end of the scope. It seems like once we move out of a local, we should be able to mark that asStorageDead
, instead of waiting until the end of the scope, which would probably fix this issue.@rustbot label +AsyncAwait-Triaged
tmandry commentedon Apr 25, 2022
In #60187 I think I attempted making a MIR building change that caused
StorageDead
to be emitted earlier. The performance hit was unacceptable for doing this for all functions (benchmark results), but there was discussion about doing this for only generators. I can't remember where exactly we landed on that, but I don't see a diff in the MIR building code of the final PR. So maybe that's the thread to pick up again from here.add test for rust-lang#96084
1 remaining item