Reduce amount of code generated by ValueDebugFormat (#8239)
I noticed that `ValueDebugFormat` was pretty common near the top of
`cargo llvm-lines`. It looked like this was probably due to the large
number of await points inserted into the code. Each await point
complicates the state machine that rustc must generate and pass to LLVM.
This reduces the number of await points from one per field to one per
struct. There's a minor change in behavior as the child fields are
awaited concurrently (`join_all`) instead of one-at-a-time.
## Why?
Less code generated by macros and passed to LLVM should mean faster
compiles and a smaller binary that we're shipping to the user. The total
change here is pretty small though, so it's probably not worth
benchmarking compile times.
## Testing
```
cargo test -p turbo-tasks-macros-tests
```
## cargo llvm-lines (sanity check)
```
cargo llvm-lines -p next-swc-napi
```
Before:
```
Lines Copies Function name
----- ------ -------------
1094257 31851 (TOTAL)
...
1246 (0.1%, 2.2%) 1 (0.0%, 0.0%) <next_swc_napi[a7ff9ed323af314d]::app_structure::ComponentsForJs as turbo_tasks[129d614a87aad753]::debug::ValueDebugFormat>::value_debug_format::{closure#0}
```
After:
```
Lines Copies Function name
----- ------ -------------
1088974 31851 (TOTAL)
...
462 (0.0%, 7.7%) 1 (0.0%, 0.3%) <next_swc_napi[a7ff9ed323af314d]::app_structure::ComponentsForJs as turbo_tasks[129d614a87aad753]::debug::ValueDebugFormat>::value_debug_format::{closure#0}
```
## Binary size (next-swc, stripped arm64 linux tarball)
Before: `188180480 bytes`
After: `187443200 bytes`
<details>
<summary><strong>Example Generated Code (After)</strong>
</summary>
```rust
// =================================================
// Recursive expansion of the ValueDebugFormat macro
// =================================================
impl turbo_tasks::debug::ValueDebugFormat for ComponentsForJs {
fn value_debug_format<'a>(
&'a self,
depth: usize,
) -> turbo_tasks::debug::ValueDebugFormatString<'a> {
turbo_tasks::debug::ValueDebugFormatString::Async(Box::pin(async move {
if depth == 0 {
return Ok(stringify!(ComponentsForJs).to_string());
}
use turbo_tasks::debug::{internal::*, ValueDebugFormat};
Ok(format!(
"{:#?}",
match self {
ComponentsForJs {
page,
layout,
error,
loading,
template,
not_found,
default,
route,
metadata,
} =>
FormattingStruct::new_named_async(
stringify!(ComponentsForJs),
vec![
AsyncFormattingField::new(
stringify!(page),
turbo_tasks::macro_helpers::value_debug_format_field(
page.value_debug_format(depth.saturating_sub(1))
),
),
AsyncFormattingField::new(
stringify!(layout),
turbo_tasks::macro_helpers::value_debug_format_field(
layout.value_debug_format(depth.saturating_sub(1))
),
),
AsyncFormattingField::new(
stringify!(error),
turbo_tasks::macro_helpers::value_debug_format_field(
error.value_debug_format(depth.saturating_sub(1))
),
),
AsyncFormattingField::new(
stringify!(loading),
turbo_tasks::macro_helpers::value_debug_format_field(
loading.value_debug_format(depth.saturating_sub(1))
),
),
AsyncFormattingField::new(
stringify!(template),
turbo_tasks::macro_helpers::value_debug_format_field(
template.value_debug_format(depth.saturating_sub(1))
),
),
AsyncFormattingField::new(
stringify!(not_found),
turbo_tasks::macro_helpers::value_debug_format_field(
not_found.value_debug_format(depth.saturating_sub(1))
),
),
AsyncFormattingField::new(
stringify!(default),
turbo_tasks::macro_helpers::value_debug_format_field(
default.value_debug_format(depth.saturating_sub(1))
),
),
AsyncFormattingField::new(
stringify!(route),
turbo_tasks::macro_helpers::value_debug_format_field(
route.value_debug_format(depth.saturating_sub(1))
),
),
AsyncFormattingField::new(
stringify!(metadata),
turbo_tasks::macro_helpers::value_debug_format_field(
metadata.value_debug_format(depth.saturating_sub(1))
),
),
],
)
.await,
}
))
}))
}
}
```
</details>