Restrict crate-internal items to pub(crate) and remove dead code it exposes#31254
Conversation
Demote pub items that are never reachable outside their defining crate (unreachable_pub) to pub(crate). Keeps dead_code analysis effective on items that were previously treated as external API roots.
The js_ast jsonStringify port (JsonWriter/BindingJsonWriter traits, Serializable carrier structs, json_stringify methods, Ast::to_json) had no implementors and no callers. bun_unicode was an empty crate with no code and no dependents.
…bun_picohttp_sys None of these are depended on by any workspace member: - bun_meta: Zig comptime-reflection helpers with no Rust callers - bun_url_jsc: single wrapper fn, never called - bun_libarchive_sys / bun_picohttp_sys: superseded by bun_libarchive / bun_picohttp which carry their own bindings - bun_node-fallbacks crate wrapper (the .js fallbacks stay; they are bundled by codegen, the Rust crate around them was empty) - crossbeam workspace dependency (no member declares it)
|
Updated 12:03 AM PT - May 24th, 2026
✅ @Jarred-Sumner, your commit a9b037440657c8fd95fb117045f4ce1273d1cea1 passed in 🧪 To try this PR locally: bunx bun-pr 31254That installs a local version of the PR into your bun-31254 --bun |
|
Warning Review limit reached
Your plan currently allows 2 reviews/hour. Refill in 11 minutes and 24 seconds. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more review capacity refills, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (267)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/js_parser/parse/parse_entry.rs (1)
357-363:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFix wasm32 mutability in
Parser::parse
src/js_parser/parse/parse_entry.rsdefinespub fn parse(self) ...(immutableselfbinding), but the#[cfg(target_arch = "wasm32")]block assigns toself.options.tsandself.options.jsx.parse. Both are plainboolfields (Options.ts: bool,options::JSX::Pragma.parse: bool), so wasm32 builds will fail to compile.💡 Proposed fix
- pub fn parse(self) -> Result<crate::Result<'a>, Error> { + pub fn parse(mut self) -> Result<crate::Result<'a>, Error> {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/js_parser/parse/parse_entry.rs` around lines 357 - 363, The parse method takes an immutable self but the wasm32 branch assigns to self.options.ts and self.options.jsx.parse; change the signature of pub fn parse(self) -> ... to pub fn parse(mut self) -> ... so self is mutable, allowing assignments to the bool fields (referencing Parser::parse, self.options.ts and self.options.jsx.parse), then keep the rest of the logic and return self._parse::<true>() as before.src/runtime/shell/subproc.rs (1)
655-668:⚠️ Potential issue | 🟠 Major | ⚡ Quick winKeep
stdin_opt/stdout_optbindings mutable on Windows (needed fordeinit(&mut self))
spawn::process::WindowsStdio::deinitis declared aspub fn deinit(&mut self)insrc/spawn/process.rs, so the Windows error-path callsstdin_opt.deinit()/stdout_opt.deinit()insrc/runtime/shell/subproc.rsrequirestdin_opt/stdout_optto bemut. Restoringmutfixes the Windows build.Suggested fix
- let stdin_opt = match stdio_guard[0].as_spawn_option(0) { + let mut stdin_opt = match stdio_guard[0].as_spawn_option(0) { stdio::ResultT::Result(opt) => opt, stdio::ResultT::Err(e) => { return Err(ShellErr::Custom(Box::<[u8]>::from(e.to_str()))); } }; @@ - let stdout_opt = match stdio_guard[1].as_spawn_option(1) { + let mut stdout_opt = match stdio_guard[1].as_spawn_option(1) { stdio::ResultT::Result(opt) => opt, stdio::ResultT::Err(e) => { #[cfg(windows)] stdin_opt.deinit(); return Err(ShellErr::Custom(Box::<[u8]>::from(e.to_str()))); } };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/runtime/shell/subproc.rs` around lines 655 - 668, The Windows build fails because the error paths call WindowsStdio::deinit(&mut self) on stdin_opt/stdout_opt but the bindings are not declared mutable; update the bindings created from stdio_guard[*].as_spawn_option(...) so that stdin_opt and stdout_opt are declared mut (e.g., change let stdin_opt / let stdout_opt to let mut stdin_opt / let mut stdout_opt) so they can be passed as &mut to WindowsStdio::deinit in the error branches (references: as_spawn_option, stdin_opt, stdout_opt, WindowsStdio::deinit, ShellErr::Custom).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/runtime/webcore/s3/client.rs`:
- Line 1133: The S3DownloadStreamWrapper is declared as a local item inside the
readable_stream function but incorrectly uses the visibility qualifier
`pub(crate)`; remove `pub(crate)` from the `S3DownloadStreamWrapper` struct
declaration and any method impls or inherent methods declared inside
`readable_stream` so they are plain (non-`pub`) local items, e.g., update the
struct and its impl blocks in the readable_stream function to drop `pub(crate)`
from the identifiers.
---
Outside diff comments:
In `@src/js_parser/parse/parse_entry.rs`:
- Around line 357-363: The parse method takes an immutable self but the wasm32
branch assigns to self.options.ts and self.options.jsx.parse; change the
signature of pub fn parse(self) -> ... to pub fn parse(mut self) -> ... so self
is mutable, allowing assignments to the bool fields (referencing Parser::parse,
self.options.ts and self.options.jsx.parse), then keep the rest of the logic and
return self._parse::<true>() as before.
In `@src/runtime/shell/subproc.rs`:
- Around line 655-668: The Windows build fails because the error paths call
WindowsStdio::deinit(&mut self) on stdin_opt/stdout_opt but the bindings are not
declared mutable; update the bindings created from
stdio_guard[*].as_spawn_option(...) so that stdin_opt and stdout_opt are
declared mut (e.g., change let stdin_opt / let stdout_opt to let mut stdin_opt /
let mut stdout_opt) so they can be passed as &mut to WindowsStdio::deinit in the
error branches (references: as_spawn_option, stdin_opt, stdout_opt,
WindowsStdio::deinit, ShellErr::Custom).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 80803f7c-2819-4331-9a79-39df8bdf80bf
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (178)
Cargo.tomlsrc/ast/ast_result.rssrc/ast/base.rssrc/ast/binding.rssrc/ast/e.rssrc/ast/expr.rssrc/ast/g.rssrc/ast/lib.rssrc/ast/nodes.rssrc/ast/op.rssrc/ast/s.rssrc/ast/scope.rssrc/ast/stmt.rssrc/ast/symbol.rssrc/bun_alloc/basic.rssrc/bun_bin/phase_c_exports.rssrc/bundler/LinkerGraph.rssrc/bundler/ParseTask.rssrc/bundler/ThreadPool.rssrc/bundler/linker.rssrc/bundler/linker_context/findImportedFilesInCSSOrder.rssrc/bundler/options.rssrc/collections/lib.rssrc/css/properties/border.rssrc/css/properties/properties_impl.rssrc/css/rules/mod.rssrc/http_jsc/websocket_client.rssrc/install/PackageManager.rssrc/install/PackageManager/PopulateManifestCache.rssrc/install/PackageManager/patchPackage.rssrc/install/PackageManager/security_scanner.rssrc/install/hoisted_install.rssrc/install/isolated_install.rssrc/install/lib.rssrc/install/lockfile/Buffers.rssrc/install/lockfile/bun.lock.rssrc/install/npm.rssrc/install/repository.rssrc/js_parser/defines_table.rssrc/js_parser/parse/parse_entry.rssrc/js_printer/lib.rssrc/jsc/ConsoleObject.rssrc/jsc/Debugger.rssrc/jsc/btjs.rssrc/jsc/cpp.rssrc/jsc/event_loop.rssrc/jsc/host_fn.rssrc/jsc/ipc.rssrc/libarchive_sys/Cargo.tomlsrc/libarchive_sys/bindings.rssrc/libarchive_sys/bindings.zigsrc/libarchive_sys/lib.rssrc/md/lib.rssrc/meta/Cargo.tomlsrc/meta/bits.zigsrc/meta/lib.rssrc/meta/meta.zigsrc/meta/tagged_union.rssrc/meta/tagged_union.zigsrc/meta/traits.zigsrc/node-fallbacks/Cargo.tomlsrc/node-fallbacks/lib.rssrc/parsers/lib.rssrc/picohttp_sys/Cargo.tomlsrc/picohttp_sys/lib.rssrc/picohttp_sys/picohttpparser.rssrc/picohttp_sys/picohttpparser.zigsrc/runtime/api/BunObject.rssrc/runtime/api/JSON5Object.rssrc/runtime/api/bun/SecureContext.rssrc/runtime/api/bun/Terminal.rssrc/runtime/api/bun/h2_frame_parser.rssrc/runtime/bake/DevServer.rssrc/runtime/bake/DevServer/ErrorReportRequest.rssrc/runtime/bake/DevServer/HmrSocket.rssrc/runtime/bake/DevServer/memory_cost.rssrc/runtime/bake/FrameworkRouter.rssrc/runtime/bake/bake_body.rssrc/runtime/bake/mod.rssrc/runtime/bake/production.rssrc/runtime/cli/audit_command.rssrc/runtime/cli/create_command.rssrc/runtime/cli/filter_run.rssrc/runtime/cli/mod.rssrc/runtime/cli/multi_run.rssrc/runtime/cli/open.rssrc/runtime/cli/package_manager_command.rssrc/runtime/cli/pm_version_command.rssrc/runtime/cli/repl.rssrc/runtime/cli/repl_command.rssrc/runtime/cli/test/parallel/runner.rssrc/runtime/cli/test_command.rssrc/runtime/crypto/CryptoHasher.rssrc/runtime/dns_jsc/dns.rssrc/runtime/ffi/FFIObject.rssrc/runtime/ffi/ffi_body.rssrc/runtime/ffi/mod.rssrc/runtime/hw_exports.rssrc/runtime/lib.rssrc/runtime/napi/napi_body.rssrc/runtime/node/node_crypto_binding.rssrc/runtime/node/node_fs.rssrc/runtime/node/node_fs_stat_watcher.rssrc/runtime/node/node_process.rssrc/runtime/node/util/parse_args.rssrc/runtime/server/RequestContext.rssrc/runtime/server/ServerWebSocket.rssrc/runtime/server/mod.rssrc/runtime/server/server_body.rssrc/runtime/shell/subproc.rssrc/runtime/socket/socket_body.rssrc/runtime/socket/tls_socket_functions.rssrc/runtime/test_runner/Order.rssrc/runtime/test_runner/ScopeFunctions.rssrc/runtime/test_runner/diff/printDiff.rssrc/runtime/test_runner/pretty_format.rssrc/runtime/timer/DateHeaderTimer.rssrc/runtime/timer/EventLoopDelayMonitor.rssrc/runtime/valkey_jsc/js_valkey.rssrc/runtime/valkey_jsc/js_valkey_functions.rssrc/runtime/webcore/Blob.rssrc/runtime/webcore/Response.rssrc/runtime/webcore/TextEncoder.rssrc/runtime/webcore/encoding.rssrc/runtime/webcore/fetch.rssrc/runtime/webcore/s3/client.rssrc/runtime/webcore/s3/error_jsc.rssrc/sourcemap/lib.rssrc/sourcemap_jsc/lib.rssrc/spawn_sys/posix_spawn.rssrc/sql_jsc/postgres/DataCell.rssrc/standalone_graph/lib.rssrc/unicode/Cargo.tomlsrc/unicode/lib.rssrc/unicode/uucode/CLAUDE.mdsrc/unicode/uucode/grapheme_gen.zigsrc/unicode/uucode/lut.zigsrc/unicode/uucode/uucode_config.zigsrc/unicode/uucode_lib/LICENSE.mdsrc/unicode/uucode_lib/README.mdsrc/unicode/uucode_lib/build.zigsrc/unicode/uucode_lib/build.zig.zonsrc/unicode/uucode_lib/src/ascii.zigsrc/unicode/uucode_lib/src/config.zigsrc/unicode/uucode_lib/src/get.zigsrc/unicode/uucode_lib/src/grapheme.zigsrc/unicode/uucode_lib/src/root.zigsrc/unicode/uucode_lib/src/types.zigsrc/unicode/uucode_lib/src/utf8.zigsrc/unicode/uucode_lib/src/x/config.x.zigsrc/unicode/uucode_lib/src/x/config_x/grapheme_break.zigsrc/unicode/uucode_lib/src/x/config_x/wcwidth.zigsrc/unicode/uucode_lib/src/x/grapheme.zigsrc/unicode/uucode_lib/src/x/root.zigsrc/unicode/uucode_lib/src/x/types.x.zigsrc/unicode/uucode_lib/src/x/types_x/grapheme.zigsrc/unicode/uucode_lib/ucd/.gitignoresrc/unicode/uucode_lib/ucd/BidiBrackets.txtsrc/unicode/uucode_lib/ucd/Blocks.txtsrc/unicode/uucode_lib/ucd/CaseFolding.txtsrc/unicode/uucode_lib/ucd/DerivedCoreProperties.txtsrc/unicode/uucode_lib/ucd/SpecialCasing.txtsrc/unicode/uucode_lib/ucd/UnicodeData.txtsrc/unicode/uucode_lib/ucd/auxiliary/GraphemeBreakProperty.txtsrc/unicode/uucode_lib/ucd/auxiliary/GraphemeBreakTest.txtsrc/unicode/uucode_lib/ucd/emoji/emoji-data.txtsrc/unicode/uucode_lib/ucd/emoji/emoji-variation-sequences.txtsrc/unicode/uucode_lib/ucd/emoji/emoji-zwj-sequences.txtsrc/unicode/uucode_lib/ucd/extracted/DerivedBidiClass.txtsrc/unicode/uucode_lib/ucd/extracted/DerivedEastAsianWidth.txtsrc/unicode/uucode_lib/ucd/extracted/DerivedGeneralCategory.txtsrc/url_jsc/Cargo.tomlsrc/url_jsc/lib.rssrc/url_jsc/url_jsc.zigsrc/uws_sys/Loop.rssrc/uws_sys/Request.rssrc/uws_sys/h3.rssrc/uws_sys/us_socket_t.rs
💤 Files with no reviewable changes (66)
- src/unicode/uucode_lib/LICENSE.md
- src/meta/Cargo.toml
- src/libarchive_sys/bindings.rs
- src/unicode/uucode_lib/README.md
- src/unicode/uucode_lib/ucd/.gitignore
- src/unicode/uucode_lib/src/x/config.x.zig
- src/sourcemap/lib.rs
- src/meta/traits.zig
- src/unicode/uucode_lib/ucd/Blocks.txt
- src/unicode/uucode_lib/src/x/types.x.zig
- src/unicode/uucode/CLAUDE.md
- src/collections/lib.rs
- src/unicode/uucode/grapheme_gen.zig
- src/unicode/uucode_lib/src/config.zig
- src/node-fallbacks/lib.rs
- src/ast/base.rs
- src/libarchive_sys/lib.rs
- src/jsc/cpp.rs
- src/unicode/uucode_lib/ucd/BidiBrackets.txt
- src/meta/tagged_union.zig
- src/unicode/uucode_lib/src/root.zig
- src/unicode/uucode_lib/src/x/config_x/grapheme_break.zig
- src/unicode/uucode/uucode_config.zig
- src/unicode/uucode_lib/src/x/root.zig
- src/meta/tagged_union.rs
- src/unicode/uucode_lib/src/x/types_x/grapheme.zig
- src/ast/symbol.rs
- src/picohttp_sys/Cargo.toml
- src/unicode/uucode_lib/src/get.zig
- src/meta/bits.zig
- src/picohttp_sys/picohttpparser.zig
- src/node-fallbacks/Cargo.toml
- src/parsers/lib.rs
- src/ast/op.rs
- src/unicode/uucode_lib/src/utf8.zig
- src/runtime/lib.rs
- src/unicode/uucode/lut.zig
- src/ast/binding.rs
- src/libarchive_sys/Cargo.toml
- src/standalone_graph/lib.rs
- src/ast/s.rs
- src/unicode/uucode_lib/src/ascii.zig
- src/picohttp_sys/picohttpparser.rs
- src/unicode/uucode_lib/src/grapheme.zig
- src/unicode/Cargo.toml
- src/picohttp_sys/lib.rs
- src/libarchive_sys/bindings.zig
- src/md/lib.rs
- src/unicode/uucode_lib/build.zig.zon
- src/ast/e.rs
- src/unicode/lib.rs
- src/meta/lib.rs
- src/unicode/uucode_lib/src/x/grapheme.zig
- src/ast/ast_result.rs
- src/ast/stmt.rs
- src/ast/lib.rs
- src/meta/meta.zig
- src/ast/scope.rs
- src/unicode/uucode_lib/build.zig
- src/sourcemap_jsc/lib.rs
- src/ast/expr.rs
- src/unicode/uucode_lib/src/x/config_x/wcwidth.zig
- src/ast/g.rs
- src/unicode/uucode_lib/src/types.zig
- Cargo.toml
- src/ast/nodes.rs
- Restore `mut` on bindings whose mutation is inside #[cfg(windows)] / #[cfg(wasm32)] blocks; the autofix pass overrode the #[cfg_attr(..., allow(unused_mut))] guards that protect them. - Drop visibility qualifiers from function-local items in s3/client.rs. - Remove comments orphaned by deleted extern-crate aliases.
Promote unreachable_pub from 50 per-crate #![warn]s (which silently downgraded any stricter setting and whose warnings were never acted on) to a single workspace-level deny. With dead_code already denied, pub now has to be true: an item that no other crate imports must be pub(crate), which keeps it under dead-code analysis. Verified with cargo check --workspace on all 10 CI target triples; the platform-gated items this surfaced (Windows shim ntdll/kernel32 externs, FreeBSD futex impl, winsock shims, napi V8 ABI symbols) are demoted to pub(super)/pub(crate) to match their sibling cfg variants.
# Conflicts: # src/jsc/btjs.rs
- The Windows .bin shim PE compiles BinLinkingShim.rs/bun_shim_impl.rs as private modules of a binary, where their pub items (cross-crate API in the bun_install lib build) are trivially unreachable. Allow the lint on those two mod declarations in the binary's main.rs only. - Demote the re-exports inside btjs.rs's private zig_std_debug/tty modules introduced by the frame-pointer-walk extraction.
A pub item in this workspace is exempted from dead_code analysis as an external API root even if no other crate imports it. This commit audits every path-addressable export against actual cross-crate usage (see scripts/find-dead-exports.ts), verified by demoting candidates to pub(crate) and letting the compiler reject the ones that are referenced through re-export chains, crate aliases, macro expansions, signatures, or platform-gated code on any of the 10 CI target triples. - ~5,000 exports no other crate references are now pub(crate) - ~870 items that were dead even within their own crate are deleted (~5,700 lines): unused FFI wrapper impls, never-enabled algorithm passes, orphaned port scaffolding, unreferenced constants and types - 235 items the compiler proved dead but that are kept deliberately are marked #[allow(dead_code)]: platform-gated code that is dead on its own platform, FFI binding-table entries, never-read fields that cannot be removed without layout changes - Binding-table crates (windows_sys, libuv_sys, the sys/windows and errno tables) keep their full pub surface by design - Review feedback: drop the crate-level #![warn(unreachable_pub)] that downgraded the workspace deny, remove comments orphaned by deleted aliases, delete the dead uucode update script Verified with cargo check --workspace on all 10 CI target triples and the standalone Windows shim build.
There was a problem hiding this comment.
I didn't find any bugs, but this is a very large refactor (862 files, ~97k lines deleted) that removes several crates and enables a workspace-wide lint, so it warrants human sign-off.
Extended reasoning...
Overview
This PR demotes pub items to pub(crate) across the workspace, enables #![deny(unreachable_pub)] workspace-wide, deletes several unconsumed crates (bun_meta, bun_url_jsc, bun_libarchive_sys, bun_picohttp_sys, bun_unicode), removes the dead AST JSON-serialization facility, and prunes empty module shells. The net result is 862 files changed with ~8k insertions and ~97k deletions.
Security risks
None apparent — the changes are visibility reductions and dead-code removal, which strictly shrink the surface area rather than expand it. No auth, crypto, or permission logic is touched in a behavior-changing way.
Level of scrutiny
High, purely due to scale. While the bulk of edits are mechanical pub → pub(crate) rewrites that the compiler enforces, the PR also removes entire crates and a serialization facility. A human should confirm those crates are genuinely unconsumed (e.g., not used by out-of-tree tooling, build scripts, or downstream consumers) and that the workspace-wide deny(unreachable_pub) won't break alternate build configurations.
Other factors
The bug-hunting system found no issues, and the changes that are purely visibility-narrowing are self-validating (Rust won't compile if something needed wider visibility). However, 862 files and wholesale crate deletion is well outside the "simple, mechanical, self-contained" bar for auto-approval. No PR timeline was available, so I have no prior reviewer context to lean on.
- Delete the #[deprecated] attribute orphaned by removing the ENABLE_ANSI_COLORS placeholder; it had re-attached to the STDERR static and deprecated the recommended replacement - Restore the lead lines of six doc comments that the deletion ranges over-consumed from the following live item - Remove four more empty impl/mod containers left behind when their only contents were deleted
# Conflicts: # src/install/lockfile.rs
generate-host-exports.ts requires the literal text 'pub fn' after a HOST_EXPORT marker, and some of the generated thunks reference these functions cross-crate. Codegen entry points are roots, same as no_mangle exports.
deinit_ok, CssImportOrderDebug, and Package::field_count are only referenced from debug_assert! / #[cfg(debug_assertions)] code, so they are dead under the release profile where dead_code = deny still applies. The earlier verification ran the dev profile only.
- Restore pub(crate) on generate_chunk/generate_js_renamer (a revert loop had promoted them, reversing main's earlier demotion) - Delete the bun_codegen crate: its only module was gutted to a comment block by the dead-code sweep and nothing invokes it - Restore the lead lines of four more doc comments truncated by the deletion ranges
generate-classes.ts resolves each class to the shortest path where its type name appears as a literal 'pub struct'/'pub type'. Demoting a payload struct to pub(crate) makes the resolver fall back to a re-export alias at a path the generated 'pub use' imports cannot resolve. These structs are codegen roots, same as the HOST_EXPORT functions.
… tests of deleted APIs - Response::make_maybe_pooled documents its safety contract; allow not_unsafe_ptr_arg_deref rather than changing the signature at six call sites - Delete the base64 test for the removed URL_SAFE_NO_PAD codec and stop the remaining decoder tests from calling the removed calc_size_upper_bound (decode into the full scratch buffer instead) - Expand the removed HiveAllocator alias inline in the hive_array tests
The checked-in defines_table.generated.rs lookup fn was demoted to pub(crate) along with the rest of the crate-internal surface; make the generator emit the same visibility so codegen:verify stays clean.
…cceeds
The JS-pseudocode blocks opened their fences with `{`, which rustdoc
parses as an attribute block in the fence info string and rejects with
"unclosed attribute block" — a hard error during doctest collection now
that warnings are denied. Use an inline code span and a text-tagged
fence instead.
# Conflicts: # src/css/selectors/selector.rs
…bility, restore truncated comments HeapLabel and named_allocator lost their last consumers when allocator<T>()/heap_label<T>()/get_zone_t<T>() were deleted, so delete them too instead of re-documenting them. calloc_items goes back to pub to match its malloc_size/free siblings in the c_thunks_for_zone! macro. Restores the lead lines of five more comments truncated by adjacent deletions.
| # Every rustc warning is an error. Individual lints below can override this | ||
| # back to "warn" (their priority 0 beats the group's -1) where a warning level | ||
| # is intentional. | ||
| warnings = { level = "deny", priority = -1 } | ||
| # `bun_asan` is set via RUSTFLAGS (`--cfg=bun_asan` + `--check-cfg=cfg(bun_asan)`) | ||
| # by scripts/build/rust.ts for asan builds; register it here so a plain | ||
| # `cargo build` / `cargo check` (without those flags) doesn't warn. | ||
| unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bun_asan)'] } | ||
| # link.exe unconditionally prints "Creating library X.dll.lib and object | ||
| # X.dll.exp" to stdout when linking each proc-macro DLL on Windows hosts; | ||
| # there is no linker flag to suppress it. The lint already exempts itself | ||
| # from `-D warnings`, so this only silences the noise. | ||
| linker_messages = "allow" |
There was a problem hiding this comment.
🔴 warnings = { level = "deny", priority = -1 } (f8b2ca0) is still breaking CI on 6 cross targets after 7b7737e's linker_messages = "allow" fix — robobun's Build #57446 (commit 72556c0, which is after 7b7737e) shows ❌ linker stderr: clang++: argument unused during compilation: '-no-pie' on aarch64-musl, x64-asan, freebsd-{x64,aarch64}, and {x64,aarch64}-android. Separately, the comment at 184-186 ("Individual lints below can override this back to 'warn' (their priority 0 beats the group's -1)") is incorrect: rustc's special warnings group recaptures any lint at warn level regardless of CLI flag order — rustc -D warnings -W unexpected_cfgs still errors with rustc's own note "-D unexpected-cfgs implied by -D warnings"; only allow or force-warn escape it — so unexpected_cfgs = { level = "warn", … } at line 191 is now silently at deny. Suggest gating -no-pie (or passing -Wno-unused-command-line-argument) in the build script for the cross targets, and rewording the comment to say only allow/force-warn override -D warnings.
Extended reasoning...
What's failing
robobun's most recent update (9:42 PM PT May 23rd) reports Build #57446 against commit 72556c0 as ❌ on six build-rust jobs — aarch64-musl, x64-asan, freebsd-x64, freebsd-aarch64, x64-android, aarch64-android — all with the identical annotation:
linker stderr: clang++: argument unused during compilation: '-no-pie' [-Wunused-command-line-argument]
git log confirms 72556c0 sits after 7b7737e ("Fix Windows release build: cfg the core_intrinsics feature, allow linker_messages"), the commit that added linker_messages = "allow" at line 196. So the follow-up that was meant to address the -D warnings fallout did not resolve these six targets, and the only commits since (02380d3 from main, 2d94380 merge) touch neither Cargo.toml nor the build scripts.
Why this is introduced by this PR
scripts/build/rust.ts and scripts/build/flags.ts are unchanged in this PR (git diff origin/main...HEAD -- scripts/build/ is empty), so clang's -no-pie stderr line was being emitted before this PR too — what changed is that f8b2ca0 added warnings = { level = "deny", priority = -1 } to [workspace.lints.rust], promoting that previously-benign rustc warning to a hard error. Circumstantial evidence in the timeline supports this: resolved comment 3292474257 enumerated Build #57240's failures (commit 81291dd, before f8b2ca0) as 42 private_bounds/private_interfaces diagnostics — no -no-pie anywhere — and the author's own reply at 03:49 UTC May 24 confirms "the workspace now also carries warnings = deny (f8b2ca0)". The -no-pie failures appear only in builds after that commit. CI's annotation harness (scripts/build/ci.ts:143) only posts on a non-zero exit code, so these are hard errors, not surfaced warnings.
The Cargo.toml comment at lines 194-195 says linker_messages "already exempts itself from -D warnings, so this only silences the noise" — but the six-target failure on a build that has linker_messages = "allow" directly contradicts that claim. The exact mechanism is not fully pinned down (candidates: the diagnostic may be emitted for a host-triple proc-macro/build-script link where [workspace.lints] flags don't apply; or the allow is being overridden by something in the cross-build RUSTFLAGS path; or the lint isn't actually self-exempting and the host build only passes because its linker driver doesn't print this), but the observable fact stands: CI is red at HEAD on 6 targets due to a change in this PR, and the author's targeted fix didn't cover them.
The comment at 184-186 is also factually wrong
Independent of the CI break, the new comment
Individual lints below can override this back to "warn" (their priority 0 beats the group's -1) where a warning level is intentional.
is incorrect for rustc's special warnings pseudo-group. Cargo's priority controls CLI flag order (-D warnings is emitted before -W unexpected_cfgs), but flag order doesn't matter for warnings: it recaptures any lint whose resolved level is "warn" regardless of where on the command line it was set. Empirically verified on both rustc 1.95.0 stable and the pinned nightly-2026-05-06:
$ echo '#[cfg(unknown)] fn f() {}' | rustc --crate-type lib --check-cfg='cfg()' -D warnings -W unexpected_cfgs -
error: unexpected `cfg` condition name: `unknown`
= note: `-D unexpected-cfgs` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(unexpected_cfgs)]`
rustc's own diagnostic note confirms the mechanism. Swapping -W → -A exits 0; --force-warn exits 0 with a warning. Only allow and force-warn escape -D warnings; level = "warn" does not.
Concrete consequence: unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bun_asan)'] } at line 191 is now effectively at deny level — a silent behavior change vs. before this PR. The check-cfg half still does its job (registers bun_asan), but level = "warn" is dead config that misleadingly suggests the lint is intentionally kept at warn. There's no current build break only because every #[cfg(bun_codegen_embed)] site already carries a per-site #[allow(unexpected_cfgs)], but the comment will mislead the next person who adds a level = "warn" entry expecting it to take effect.
Step-by-step proof (CI break)
- Commit f8b2ca0 adds
warnings = { level = "deny", priority = -1 }to[workspace.lints.rust]. Cargo translates this to--deny=warningson every workspace crate's rustc invocation. - On the six listed cross targets, the rustc-driven link step produces
clang++: argument unused during compilation: '-no-pie'on stderr (rustc itself injects-no-pieinto the linker driver invocation when-Crelocation-model=staticis set inscripts/build/rust.ts, and on musl/android/freebsd clang treats it as unused). rustc surfaces that as alinker_messageswarning prefixedwarning: linker stderr: …. - Under
-D warnings, that warning is now a hard error →build-rustexits non-zero →scripts/build/ci.ts:143posts the ❌ annotation → robobun reports the failure. - Commit 7b7737e adds
linker_messages = "allow"to[workspace.lints.rust]. This fixes the Windows host build (per the commit message), but Build #57446 against the next commit 72556c0 shows the same six non-Windows targets still failing with the identical message — i.e., on those targets theallowis not reaching whatever rustc invocation emits the diagnostic. - No commit between 72556c0 and HEAD (2d94380) touches the lint table or build scripts.
Fix
Two independent edits:
- CI break: since the lint-table
allowdemonstrably isn't reaching these targets, fix it at the source — either gate-Crelocation-model=static(and thus rustc's-no-pieinjection) to glibc-only targets inscripts/build/rust.ts, or append-Wno-unused-command-line-argumentto the linker-driver flags so clang stops emitting the message. Setting-A linker_messagesviaRUSTFLAGSin the build script would also work (RUSTFLAGS reaches every rustc invocation, including host proc-macro links, unlike[workspace.lints]). - Incorrect comment: reword 184-186 to say that only
allow(orforce-warn) overrides-D warnings;level = "warn"is recaptured. Optionally drop the no-oplevel = "warn"from theunexpected_cfgsentry (thecheck-cfgkey is the only part doing work), and revisit the line-195 "exempts itself from-D warnings" claim in light of the CI evidence.
| /// `to_source_at` rooted at the process CWD. | ||
| pub fn to_source(path: &bun_core::ZStr, opts: ToSourceOptions) -> bun_sys::Result<Source> { |
There was a problem hiding this comment.
🟡 One more orphaned-reference instance not in the open #22/#25/#26/#27 lists or resolved #16: the doc on pub fn to_source (line 3186) reads "/// to_source_at rooted at the process CWD." — but this PR deletes the local pub fn to_source_at wrapper it described (the hunk immediately above). The remaining to_source_at hits (lines 2663/3167, transpiler.rs:1828) are the unrelated bun_sys::File::to_source_at. Same fix as the prior sweeps — reword to reference source_from_file_at (or source_from_file). Doc-only, no build/runtime effect.
Extended reasoning...
What was left behind
Same orphaned-reference-to-deleted-item category as resolved comment #16 (3292377782: live_arena_heaps/DumpOptions/allocator_has_pointer/heap::leak/allocator<T>), which the author accepted and swept in f8b2ca0. This is one more instance not enumerated in #16 or in any of the open lists (#22 covers Package.rs/layer.rs/selectors/effects/list; #25 c_thunks; #26 heap_breakdown HeapLabel/named_allocator; #27 ParentDeathWatchdog/keyframes/ident/dependency).
The doc comment on pub fn to_source at src/ast/lib.rs:3186 reads:
/// `to_source_at` rooted at the process CWD.
pub fn to_source(path: &bun_core::ZStr, opts: ToSourceOptions) -> bun_sys::Result<Source> {
source_from_file(path, opts)
}It describes to_source as "to_source_at rooted at CWD" — but this PR's hunk @@ -3222,15 +3183,6 @@ (immediately above this line in the diff) deletes the local pub fn to_source_at wrapper it referred to:
-/// Read `path` (relative to `dir_fd`) into memory and wrap it in a `Source`.
-pub fn to_source_at(
- dir_fd: bun_sys::Fd,
- path: &bun_core::ZStr,
- opts: ToSourceOptions,
-) -> bun_sys::Result<Source> {
- source_from_file_at(dir_fd, path, opts)
-}
-
/// `to_source_at` rooted at the process CWD.
pub fn to_source(...)The doc now describes to_source in terms of a sibling function that no longer exists.
Step-by-step proof
- Before this PR,
src/ast/lib.rsdefined two thin wrappers in this module:pub fn to_source_at(dir_fd, path, opts)(forwarding tosource_from_file_at) andpub fn to_source(path, opts)(forwarding tosource_from_file). The doc onto_source— "///to_source_atrooted at the process CWD." — accurately described it as the CWD-rooted variant of its siblingto_source_at. - This PR deletes
pub fn to_source_at(visible as a 9-line removal in the diff hunk@@ -3222,15 +3183,6 @@) but leaves the doc onto_sourceas an unchanged context line. - At HEAD, line 3186 still reads
///to_source_atrooted at the process CWD.and line 3187 ispub fn to_source(...).rg to_source_at src/returns five hits:src/ast/lib.rs:3186— this stale doc (the only reference to the deleted local fn).src/ast/lib.rs:2663and:3167— references tobun_sys::File::to_source_at(a different method in a different namespace; theMOVE_DOWNprovenance comment onsource_from_file_at).src/bundler/transpiler.rs:1828— alsoFile::to_source_at(provenance comment).src/runtime/cli/pack_command.rs:71— an unrelated localfn file_to_source_at(different identifier).
- No local
to_source_atexists anymore in this module; the doc's referent is gone.
Why nothing prevents it
Same as every prior instance in this PR: the compiler doesn't lint doc-comment prose, and the dead-code deletion only touched the item, not the adjacent prose that referenced it. cargo check --workspace (the PR's stated verification) doesn't run rustdoc, and rustdoc wouldn't flag a backtick-quoted identifier that isn't an intra-doc link anyway.
Impact
Documentation-only — zero build, lint, or runtime effect. Same lowest-tier-of-nit category as the ~16+ orphaned-reference instances the author has already accepted and swept across d8ee30d / 01fc54b / 3f63077 / 7915136 / 9abf984 / f8b2ca0. Filed only because (a) it's exactly the category resolved #16 covered, (b) src/ast/lib.rs:3186 isn't enumerated in any open or resolved list, and (c) the diff context proves the deletion and the surviving doc are in the same hunk.
Fix
Reword line 3186 to reference the surviving sibling, e.g.:
/// `source_from_file_at` rooted at the process CWD.
or simply /// source_from_file convenience wrapper. — either restores a valid referent.
There was a problem hiding this comment.
Reworded in a9b0374 — the doc now references source_from_file_at.
| const SEG_LINKEDIT: &[u8] = b"__LINKEDIT"; | ||
|
|
||
| pub mod utils { | ||
| use super::macho; | ||
|
|
||
| pub fn is_elf(data: &[u8]) -> bool { | ||
| if data.len() < 4 { | ||
| return false; | ||
| } | ||
| u32::from_be_bytes(data[0..4].try_into().expect("infallible: size matches")) == 0x7f454c46 | ||
| } | ||
|
|
||
| pub fn is_macho(data: &[u8]) -> bool { | ||
| if data.len() < 4 { | ||
| return false; | ||
| } | ||
| u32::from_le_bytes(data[0..4].try_into().expect("infallible: size matches")) | ||
| == macho::MH_MAGIC_64 | ||
| } | ||
| } | ||
|
|
||
| const CSMAGIC_CODEDIRECTORY: u32 = 0xfade0c02; |
There was a problem hiding this comment.
🟡 The "Optionally" sub-item of resolved comment 3292362121 was missed: src/exe_format/elf.rs:527 still says "Do not route macho::utils::is_elf through this; that function is intentionally a 4-byte-magic-only sniff…" — but f8b2ca0 deleted pub mod utils from macho.rs entirely (the author's reply enumerated only the four primary items, not elf.rs). Same orphaned-reference-to-deleted-item category as resolved #16 and open #29; doc-only, no build/runtime effect — delete or reword the sentence at elf.rs:526-529.
Extended reasoning...
What was left behind
Resolved inline comment 3292362121 (#15, on src/install/lib.rs) listed five sub-items — four empty-container shells plus a final "Optionally also drop the stale macho::utils::is_elf reference in the comment at src/exe_format/elf.rs:527". The author's f8b2ca0 reply (3293857203) enumerated exactly four fixes: "deleted impl DependencyInstallContext {}, both pub mod utils {} shells in macho.rs/pe.rs (and the orphaned PE doc comment), and css/properties/contain.rs plus its pub mod contain; declaration" — the elf.rs sub-item is not mentioned, and the thread was marked resolved.
At HEAD, src/exe_format/elf.rs:525-529 reads:
/// Full ELF64-LE header validation (magic + class + endian). This is the strict
/// check used before parsing program/section headers — NOT a format sniff. Do
/// not route `macho::utils::is_elf` through this; that function is intentionally
/// a 4-byte-magic-only sniff used for elf-vs-macho dispatch and must accept
/// 32-bit/BE ELF.
But this PR's macho.rs diff at @@ -797,25 +797,6 @@ deletes the entire pub mod utils { pub fn is_elf(data: &[u8]) -> bool {…} pub fn is_macho(data: &[u8]) -> bool {…} } block (and f8b2ca0 then deleted the empty pub mod utils {} shell that remained). The doc comment now warns readers not to route a function through this code path that no longer exists anywhere in the tree.
Step-by-step proof
- Resolved comment 3292362121 explicitly listed as its final sub-item: "Optionally also drop the stale
macho::utils::is_elfreference in the comment at src/exe_format/elf.rs:527". - Commit f8b2ca0 (the author's response) deleted
impl DependencyInstallContext {}, the twopub mod utils {}shells in macho.rs/pe.rs, the orphaned PE doc comment, andcontain.rs+ its mod declaration. The author's reply (3293857203) enumerated exactly those four items and did not mention elf.rs. - At HEAD,
grep -rn 'macho::utils\|utils::is_elf\|utils::is_macho' src/returns exactly one hit:src/exe_format/elf.rs:527. grep -rn 'pub mod utils' src/exe_format/returns zero hits — the module the comment references is gone.git log --oneline -- src/exe_format/elf.rsshows no commit since the PR base touched lines 525-529.
Why nothing prevents it
Same as every prior orphaned-reference instance in this PR: rustc doesn't lint doc-comment prose, and rustdoc doesn't validate backtick-quoted identifiers that aren't intra-doc […] links. cargo check --workspace (the PR's stated verification) doesn't run rustdoc.
Same pattern as accepted follow-ups
This is the incomplete-fix-of-resolved-comment shape the author has already accepted three times in this PR's review cycle:
- #3292016403 (
opaque_callback): d8ee30d fixed 3 of 4 items in a resolved thread; follow-up flagged the 4th → fixed in 3f63077. - #3292365164 (heap_breakdown parenthetical): 9abf984 restored the lead line but skipped the parenthetical sub-item; follow-up flagged it → fixed in f8b2ca0.
- #3293929698 (
fileToCrate): 00d7859 fixed the primary impl-skip bug but skipped the secondary dead-Map sub-item; follow-up flagged it → fixed in 672ec73.
It is also the same orphaned-reference-to-deleted-item category as resolved #16 (live_arena_heaps/DumpOptions/allocator_has_pointer/heap::leak/allocator<T> — all swept in f8b2ca0) and open #29 (3293966588, to_source_at in ast/lib.rs:3186). Not a duplicate of any open comment: checked #22/#23/#25/#26/#27/#28/#29/#30 — none mention elf.rs.
Impact
Documentation-only — zero build, lint, or runtime effect. Lowest tier of nit. The comment is now actively misleading (it tells readers not to route a function that doesn't exist through this validator), but validate_elf64_le is a private fn so the rustdoc isn't externally rendered. Filed only because (a) it directly contradicts a resolved-comment claim, (b) it's exactly the dead-prose category this PR explicitly targets, and (c) the author has accepted this exact follow-up shape three times already.
Fix
Delete or reword the second sentence at elf.rs:526-529. Simplest is to truncate after "NOT a format sniff.":
/// Full ELF64-LE header validation (magic + class + endian). This is the strict
/// check used before parsing program/section headers — NOT a format sniff.
| // TODO(port): Zig source is `css.DefineEnumProperty(@compileError(css.todo_stuff.depth))`. | ||
| pub enum ImageRendering {} | ||
|
|
||
| // ported from: src/css/properties/svg.zig |
There was a problem hiding this comment.
🟡 Two more comment-only file modules not in #22's enumeration: src/css/properties/svg.rs (was 30 lines of placeholder enums, now 1 comment line; mod.rs:189 still declares pub mod svg;) and src/sql_jsc/postgres/types/bool.rs (was 12 lines, now 1 comment line; postgres.rs:80-81 still declares #[path = "bool.rs"] pub mod r#bool;). Same shape and same fix as #15's contain.rs (deleted in f8b2ca0) and #22's effects.rs/list.rs — delete the files and their pub mod declarations.
Extended reasoning...
What was left behind
This is the same comment-only-file-module residue as resolved #15 (3292362121, which enumerated css/properties/contain.rs — deleted in f8b2ca0) and open #22 (3293839135, which enumerates css/properties/effects.rs + list.rs). Two more instances were gutted by commit 3f63077 (this PR's audit commit) but appear in neither enumeration:
| File | Before | After | Orphaned declaration |
|---|---|---|---|
src/css/properties/svg.rs |
30 lines (7 placeholder pub enum types: StrokeLinecap/StrokeLinejoin/ColorInterpolation/ColorRendering/ShapeRendering/TextRendering/ImageRendering) |
1 line: // ported from: src/css/properties/svg.zig |
src/css/properties/mod.rs:189 — pub mod svg; |
src/sql_jsc/postgres/types/bool.rs |
12 lines | 1 line: // ported from: src/sql_jsc/postgres/types/bool.zig |
src/sql_jsc/postgres.rs:80-81 — #[path = "bool.rs"] pub mod r#bool; inside the inline pub mod types { ... } block |
Why this would be missed when #22 is addressed
Open #22 enumerates exactly six locations: Package.rs:3152, layer.rs:22, selector.rs:42/selectors/mod.rs:60 (local_identifier), and css/properties/effects.rs + list.rs. The author's demonstrated pattern across this PR's ~12 review rounds is to fix exactly the enumerated locations — e.g., resolved #15 listed four locations (DependencyInstallContext, macho/pe utils, contain.rs), the author swept exactly those four in f8b2ca0, and then #22 found effects.rs/list.rs which #15 had missed. svg.rs and bool.rs are not in #22's list, so when #22 is addressed they would be missed again unless enumerated separately.
Why nothing catches it
Same as every prior comment-only-file-module instance: an empty file module compiles to nothing. dead_code analyzes items, not item containers — a module with zero items has nothing to flag. The new unreachable_pub = "deny" likewise only fires on pub items inside an unreachable path, not on a reachable pub mod with zero items. cargo check --workspace (the PR's stated verification) passes cleanly.
Step-by-step proof (svg.rs)
- Before this PR (verified via
git show 4df6154f:src/css/properties/svg.rs | wc -l→ 30), the file contained 7 placeholder enum types with noparse/to_cssimpls — e.g.,pub enum StrokeLinecap { Butt, Round, Square }. - Commit 3f63077 (this PR's "Audit cross-crate exports" commit) deleted all 7 types as dead — none were referenced anywhere — leaving only the
// ported from:footer line. The cumulative PR diff for this file shows 29 lines deleted. - At HEAD,
wc -l src/css/properties/svg.rsreturns 1; the file's entire content is// ported from: src/css/properties/svg.zig.src/css/properties/mod.rs:189still readspub mod svg;. - The same verification applies to
bool.rs: 1 line at HEAD,#[path = "bool.rs"] pub mod r#bool;still atsrc/sql_jsc/postgres.rs:80-81.
Impact
Zero build, lint, or runtime effect — purely cosmetic, the lowest tier of nit. Filed only because (a) this PR's stated purpose is removing exactly this category of dead-code residue, (b) the author has already accepted and swept the identical pattern (contain.rs in f8b2ca0, with #22 open for effects.rs/list.rs), and (c) without explicit enumeration these two would survive the #22 sweep.
Fix
Same treatment as contain.rs in f8b2ca0:
- Delete
src/css/properties/svg.rsand thepub mod svg;line atsrc/css/properties/mod.rs:189. - Delete
src/sql_jsc/postgres/types/bool.rsand the#[path = "bool.rs"] pub mod r#bool;lines atsrc/sql_jsc/postgres.rs:80-81.
#31254 landed on main with `#![deny(unreachable_pub)]`. The prompt_signal module was introduced before that merge with `pub fn install` / `pub struct Guard` / `pub fn uv_tty_reset_mode` — the externally-visible items need to be pub(crate), and the extern fn decl needs no visibility at all.
…t for 1.4 - bun_core::parse_ms(): npm ms-style duration parser (y/w/d/h/m/s/ms), re-exported as bun_core::parse_ms. Both --minimum-release-age and [install].minimumReleaseAge accept '2d'/'1 week'/'48h' etc.; a bare number (quoted or not) stays seconds for backwards compat. Inputs are trimmed before the seconds-parse and NaN/inf are rejected. - ConfigVersion::V2, gated: CURRENT stays V1 until feature_flags::BREAKING_CHANGES_1_4 flips for 1.4; MAX_KNOWN is V2 so newer lockfiles clamp to the highest version we understand. The BUN_FEATURE_FLAG_INSTALL_CONFIG_V2 env var opts fresh projects into V2 at runtime for testing. - PackageManager::apply_config_version_defaults(): derives config_version from the load result, applies the env-var V2 promotion for fresh projects, sets the 2-day default for V2, normalises 0 -> None. Idempotent (guards on config_version.is_some()) so the update -i -> install_with_manager double-call doesn't re-apply after an explicit 0. Wired into install_with_manager, outdated, update -i, and pm trust (so trust preserves the lockfile's configVersion on save). - re-add BREAKING_CHANGES_1_4 (removed as dead code in #31254; this PR is its first consumer). - docs: minimumReleaseAge default is configVersion-dependent. - test harness strips BUN_FEATURE_FLAG_INSTALL_CONFIG_V2 so ambient exports don't leak into fresh-project install tests. - bake-codegen: JSON.stringify(OVERLAY_CSS) so pre-#30679 bootstrap buns can build this source.
…t for 1.4 - bun_core::parse_ms(): npm ms-style duration parser (y/w/d/h/m/s/ms), re-exported as bun_core::parse_ms. Both --minimum-release-age and [install].minimumReleaseAge accept '2d'/'1 week'/'48h' etc.; a bare number (quoted or not) stays seconds for backwards compat. Inputs are trimmed before the seconds-parse and NaN/inf are rejected. - ConfigVersion::V2, gated: CURRENT stays V1 until feature_flags::BREAKING_CHANGES_1_4 flips for 1.4; MAX_KNOWN is V2 so newer lockfiles clamp to the highest version we understand. The BUN_FEATURE_FLAG_INSTALL_CONFIG_V2 env var opts fresh projects into V2 at runtime for testing. - PackageManager::apply_config_version_defaults(): derives config_version from the load result, applies the env-var V2 promotion for fresh projects, sets the 2-day default for V2, normalises 0 -> None. Idempotent (guards on config_version.is_some()) so the update -i -> install_with_manager double-call doesn't re-apply after an explicit 0. Wired into install_with_manager, outdated, update -i, and pm trust (so trust preserves the lockfile's configVersion on save). - re-add BREAKING_CHANGES_1_4 (removed as dead code in #31254; this PR is its first consumer). - docs: minimumReleaseAge default is configVersion-dependent. - test harness strips BUN_FEATURE_FLAG_INSTALL_CONFIG_V2 so ambient exports don't leak into fresh-project install tests. - bake-codegen: JSON.stringify(OVERLAY_CSS) so pre-#30679 bootstrap buns can build this source.
…t for 1.4 - bun_core::parse_ms(): npm ms-style duration parser (y/w/d/h/m/s/ms), re-exported as bun_core::parse_ms. Both --minimum-release-age and [install].minimumReleaseAge accept '2d'/'1 week'/'48h' etc.; a bare number (quoted or not) stays seconds for backwards compat. Inputs are trimmed before the seconds-parse and NaN/inf are rejected. - ConfigVersion::V2, gated: CURRENT stays V1 until feature_flags::BREAKING_CHANGES_1_4 flips for 1.4; MAX_KNOWN is V2 so newer lockfiles clamp to the highest version we understand. The BUN_FEATURE_FLAG_INSTALL_CONFIG_V2 env var opts fresh projects into V2 at runtime for testing. - PackageManager::apply_config_version_defaults(): derives config_version from the load result, applies the env-var V2 promotion for fresh projects, sets the 2-day default for V2, normalises 0 -> None. Idempotent (guards on config_version.is_some()) so the update -i -> install_with_manager double-call doesn't re-apply after an explicit 0. Wired into install_with_manager, outdated, update -i, and pm trust (so trust preserves the lockfile's configVersion on save). - re-add BREAKING_CHANGES_1_4 (removed as dead code in #31254; this PR is its first consumer). - docs: minimumReleaseAge default is configVersion-dependent. - test harness strips BUN_FEATURE_FLAG_INSTALL_CONFIG_V2 so ambient exports don't leak into fresh-project install tests. - bake-codegen: JSON.stringify(OVERLAY_CSS) so pre-#30679 bootstrap buns can build this source.
…t for 1.4 - bun_core::parse_ms(): npm ms-style duration parser (y/w/d/h/m/s/ms), re-exported as bun_core::parse_ms. Both --minimum-release-age and [install].minimumReleaseAge accept '2d'/'1 week'/'48h' etc.; a bare number (quoted or not) stays seconds for backwards compat. Inputs are trimmed before the seconds-parse and NaN/inf are rejected. - ConfigVersion::V2, gated: CURRENT stays V1 until feature_flags::BREAKING_CHANGES_1_4 flips for 1.4; MAX_KNOWN is V2 so newer lockfiles clamp to the highest version we understand. The BUN_FEATURE_FLAG_INSTALL_CONFIG_V2 env var opts fresh projects into V2 at runtime for testing. - PackageManager::apply_config_version_defaults(): derives config_version from the load result, applies the env-var V2 promotion for fresh projects, sets the 2-day default for V2, normalises 0 -> None. Idempotent (guards on config_version.is_some()) so the update -i -> install_with_manager double-call doesn't re-apply after an explicit 0. Wired into install_with_manager, outdated, update -i, and pm trust (so trust preserves the lockfile's configVersion on save). - re-add BREAKING_CHANGES_1_4 (removed as dead code in #31254; this PR is its first consumer). - docs: minimumReleaseAge default is configVersion-dependent. - test harness strips BUN_FEATURE_FLAG_INSTALL_CONFIG_V2 so ambient exports don't leak into fresh-project install tests. - bake-codegen: JSON.stringify(OVERLAY_CSS) so pre-#30679 bootstrap buns can build this source.
…t for 1.4 - bun_core::parse_ms(): npm ms-style duration parser (y/w/d/h/m/s/ms), re-exported as bun_core::parse_ms. Both --minimum-release-age and [install].minimumReleaseAge accept '2d'/'1 week'/'48h' etc.; a bare number (quoted or not) stays seconds for backwards compat. Inputs are trimmed before the seconds-parse and NaN/inf are rejected. - ConfigVersion::V2, gated: CURRENT stays V1 until feature_flags::BREAKING_CHANGES_1_4 flips for 1.4; MAX_KNOWN is V2 so newer lockfiles clamp to the highest version we understand. The BUN_FEATURE_FLAG_INSTALL_CONFIG_V2 env var opts fresh projects into V2 at runtime for testing. - PackageManager::apply_config_version_defaults(): derives config_version from the load result, applies the env-var V2 promotion for fresh projects, sets the 2-day default for V2, normalises 0 -> None. Idempotent (guards on config_version.is_some()) so the update -i -> install_with_manager double-call doesn't re-apply after an explicit 0. Wired into install_with_manager, outdated, update -i, and pm trust (so trust preserves the lockfile's configVersion on save). - re-add BREAKING_CHANGES_1_4 (removed as dead code in #31254; this PR is its first consumer). - docs: minimumReleaseAge default is configVersion-dependent. - test harness strips BUN_FEATURE_FLAG_INSTALL_CONFIG_V2 so ambient exports don't leak into fresh-project install tests. - bake-codegen: JSON.stringify(OVERLAY_CSS) so pre-#30679 bootstrap buns can build this source.
…ants Environment::IS_X64 and IS_AARCH64 became pub(crate) in #31254, which broke compilation of abort_for_unsupported_simdutf on the merge ref. Arch checks outside bun_core use cfg!(target_arch) directly.
…ants Environment::IS_X64 and IS_AARCH64 became pub(crate) in #31254, which broke compilation of abort_for_unsupported_simdutf on the merge ref. Arch checks outside bun_core use cfg!(target_arch) directly.
#31254 landed on main with `#![deny(unreachable_pub)]`. The prompt_signal module was introduced before that merge with `pub fn install` / `pub struct Guard` / `pub fn uv_tty_reset_mode` — the externally-visible items need to be pub(crate), and the extern fn decl needs no visibility at all.
#31254 landed on main with `#![deny(unreachable_pub)]`. The prompt_signal module was introduced before that merge with `pub fn install` / `pub struct Guard` / `pub fn uv_tty_reset_mode` — the externally-visible items need to be pub(crate), and the extern fn decl needs no visibility at all.
What
Three commits, one sweep:
pub→pub(crate)for 1,298 items across 105 files. Applied mechanically viacargo fixdriven by theunreachable_publint, which only fires on items that are provably unreachable from outside their defining crate — so the demotion cannot change what compiles. Two items (addrinfo/freeaddrinfore-exports inbun_dns) were reverted by hand because a chainedpub usere-exports them.Remove the dead AST JSON-serialization facility. The
js_astjsonStringifyport —JsonWriter/BindingJsonWritertraits,Serializablecarrier structs, 26json_stringifymethods,Ast::to_json— has zero trait implementors and zero callers. The only.json_stringify()call sites in the tree areJSValue's nativeJSON.stringify, which is unrelated.Remove six crates nothing depends on, plus the data files vendored under them:
bun_unicode— emptylib.rs, no consumers, but carried the entire vendored Unicode Character Database (~70k lines of.txt)bun_libarchive_sys/bun_picohttp_sys— superseded duplicates;bun_libarchive/bun_picohttpcarry their own bindings and are what everything actually usesbun_meta,bun_url_jsc— zero callersbun_node-fallbackscrate wrapper (the.jsfallback modules stay; codegen bundles those directly)crossbeamfrom[workspace.dependencies](no member declares it)After this, every workspace crate except the two standalone build roots (
bun_codegen,bun_shim_impl) has at least one in-workspace dependent.Why
dead_code = "deny"is already enforced workspace-wide, but it treats everypubitem as an external API root and never analyzes it. In a workspace where every crate is an internal implementation detail of one binary, that exemption swallows real dead code. Demoting crate-internal items topub(crate)puts them back under the lint — that is what surfaced the dead serialization facility.Verification
cargo check --workspace --lib --binsclean under the workspace's normal lint setbundler_edgecase103 pass / 0 fail,bundler_browser12 pass / 0 fail (node-fallbacks path),bun-addfailures are pre-existing on main (registry config leak in the test environment, identical signature with an unmodified build)