I tried this code (playground link) which wraps a future in a trivial async block:
let foo = async move { ... };
dbg!(std::mem::size_of_val(&foo));
let bar = async move { foo.await };
dbg!(std::mem::size_of_val(&bar));
I expected to see that size_of(bar) == size_of(foo) (plus some bytes for a tag). Instead, I found that size_of(bar) > 2 * size_of(foo).
I discovered this while nesting a couple of futures which largely had the following form:
let future = function_returning_future(...);
async move {
let result = future.await;
let output = /* ...do something with result... */;
output
}
The final future occupied a few kilobytes. I was able work around this by using a map combinator, but it is not ideal.
This could possibly be related to #62958, but I'm not familiar enough with the compiler internals to say with certainty if async-block captures are implemented the same way as async fn arguments.
Meta
This happens in stable 1.67.1, beta 1.70.0, and the latest nightly.
I tried this code (playground link) which wraps a future in a trivial
asyncblock:I expected to see that
size_of(bar) == size_of(foo)(plus some bytes for a tag). Instead, I found thatsize_of(bar) > 2 * size_of(foo).I discovered this while nesting a couple of futures which largely had the following form:
The final future occupied a few kilobytes. I was able work around this by using a
mapcombinator, but it is not ideal.This could possibly be related to #62958, but I'm not familiar enough with the compiler internals to say with certainty if
async-block captures are implemented the same way asasync fnarguments.Meta
This happens in stable 1.67.1, beta 1.70.0, and the latest nightly.