next.js
b56f1555 - turbopack: gate ValueDebugFormat and ValueDebug behind debug_assertions (#92628)

Commit
42 days ago
turbopack: gate ValueDebugFormat and ValueDebug behind debug_assertions (#92628) ### What? Gate `ValueDebugFormat` and `ValueDebug` behind `#[cfg(debug_assertions)]` across the turbopack crates, eliminating all debug formatting machinery from release binaries entirely. ### Why? `ValueDebugFormat` and `ValueDebug` contribute to release binary bloat. The field-level formatting logic (iterating struct fields, resolving `Vc`s, formatting collections recursively) and the per-type `ValueDebug` trait registrations are purely debugging aids with no value in production binaries. **Measured impact: -7.3 MiB (-5.5%) reduction in release `libnext_napi_bindings.so` binary size** (from 126.26 MiB to 119.31 MiB). ### How? **`ValueDebug` trait** (`debug/mod.rs`): - In debug builds: full `#[turbo_tasks::value_trait(no_debug)]` with `dbg()` / `dbg_depth()` methods, `ValueDebugFormatString`, all blanket impls for collections/tuples/etc. - In release builds: empty marker trait with blanket `impl<T: ?Sized> ValueDebug for T {}`. This satisfies the supertrait bound on all value traits at zero cost — no per-type impl code is generated. **`ValueDebugFormat` trait** (`debug/mod.rs`): - The `value_debug_format` method only exists under `#[cfg(debug_assertions)]`. In release builds, the trait is still present (for derive macros to reference) but has no methods. - All blanket impls (`String`, `RcStr`, `Option`, `Vec`, `SmallVec`, `AutoSet`, `AutoMap`, `HashMap`, `FxIndexSet`, `FxIndexMap`, tuples) are gated behind `debug_assertions`. - Supporting infrastructure (`ValueDebugFormatString`, `PassthroughDebug`, `vdbg`, `internal` submodule, `value_debug_format_field`) is compiled away. **Proc-macros**: - `#[derive(ValueDebugFormat)]`: emits a full impl with `value_debug_format` method in debug builds, empty impl in release builds. - `#[derive(ValueDebug)]` and `value_impl` blocks: emit full debug impl in debug builds only — **no release impl at all** (the blanket marker trait impl covers it). - `#[turbo_tasks::value]`: transparent types get `#[cfg(debug_assertions)]` on the manual `ValueDebug` impl. Non-transparent types use `#[cfg_attr(debug_assertions, derive(turbo_tasks::debug::internal::ValueDebug))]` so the `internal` module is never referenced in release. - `#[turbo_tasks::value_trait]`: the `Dynamic/Upcast/UpcastStrict` impls for `Box<dyn ValueDebug>` are gated behind `#[cfg(debug_assertions)]`. **Callers** (`vc/mod.rs`, `vc/resolved.rs`, `read_ref.rs`, `mapped_read_ref.rs`, `macro_helpers.rs`, `alias_map.rs`): - All `impl ValueDebugFormat` blocks and their imports are gated behind `#[cfg(debug_assertions)]`. ### Verification - `cargo check --release` — clean (no errors, no warnings) - `cargo clippy --all-targets` — clean - CI passing <!-- NEXT_JS_LLM_PR --> --------- Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
Author
Parents
Loading