Skip to content

Remove dead code from the bundler, the resolver, bun_css, the Valkey client, and six smaller areas - #45723

Open
robobun wants to merge 1 commit into
mainfrom
robobun/124c7e92/dead-code-sweep
Open

robobun wants to merge 1 commit into
mainfrom
robobun/124c7e92/dead-code-sweep

Conversation

@robobun

@robobun robobun commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

Behaviour change: none

Problem

  • 26 groups of lines in 57 files cannot run or hold a value that nothing reads: options that only hold their default, empty hooks, parameters with one value at every call site, results that are never Err.
  • No lint reports them. rustc counts a store as a use of a field, and a branch on a parameter as live.

Fix

  • Delete them: 1,459 lines removed, 288 added (call sites that lose an argument, code that an always-true if wrapped). The Notes give each item and its proof.
  • Each proof is a search that shows every writer, reader or caller. Where a flag is never set, the last Zig tree never set it either, so none is a port regression.
  • Verified: bun bd, cargo check for the 12 CI targets, cargo clippy, 17 test files with the debug build (Notes).

Background

  • Most of this came with ported code (esbuild's linker, lightningcss, Zig's password API) for features Bun never turns on. Example: BundleOptions.write is false at every assignment, so open_output_dir cannot run.
  • Write-only means code stores a value and no code loads it. Example: ParseOptions.macro_remappings was deep-cloned per module load and then dropped.
  • No other design was weighed: a deletion has one place.

Downsides

  • None found for users. Checked: every CI target compiles without the removed items, and the tests in the Notes pass.
  • An open PR that starts to use a removed item fails to compile after this merges.
Notes

Removed, by area

Bundler (src/bundler, callers in src/jsc and src/runtime)

  1. allocator_to_use of IntermediateOutput::code, code_standalone and code_with_source_map_shifts, with allocator_for_size and the arena argument of alloc_buf. type DynAlloc = (), and all 7 callers pass None.
  2. BundleOptions.write, TransformOptions.write, output_dir_handle, open_output_dir and TransformOutstream. write is Some(false) at each of its three assignments.
  3. ParseOptions.macro_remappings, its three producers (a deep clone of the macro map) and VirtualMachine.has_any_macro_remappings. The only reader was let _ = &this_parse.macro_remappings;.
  4. BundleOptions.out_extensions and TargetExt::out_extensions. The map was built on each Transpiler init and cloned into each worker. Nothing looks anything up in it.
  5. ServerComponentParseTask::Data::ClientEntryWrapper, the ClientEntryWrapper struct and generate_client_entry_wrapper. The variant existed only as the placeholder of impl Default, which the one caller overwrote. ServerComponentParseTask::new replaces that Default impl.
  6. client_entry_point_ of Transpiler::parse, parse_maybe_return_file_only, parse_maybe_return_file_only_allow_shared_buffer and build_with_resolve_result_eager, and entry_points::ClientEntryPoint. Every call site passes None.
  7. to_parser_module_type and to_bundle_enums_target (argument and result are the same type), and the empty impl Drop for BundleOptions.

Resolver (src/resolver)
8. cache::Fs.stream (always false) and size_hint (always None) of the file reader. With them go the STREAM const generic, the re-stat and re-read loop, both size_hint matches, and the unread path of read_file_contents_in_arena.
9. The platform parameter of the five helpers of the private bun_paths shim, and dispatch_platform!. Every caller passes Platform::AUTO, which names the same platform as platform::Auto on each target.

Valkey client (src/runtime/valkey_jsc, src/valkey)
10. The Result of JSValkeyClient::send, ValkeyClient::send, enqueue, Entry::create and Command::serialize. The only fallible step writes to a Vec<u8>, and bun_io::Write for Vec<u8> always returns Ok. With it go send_err_to_js, 31 "Failed to send" arguments, RedisError::JSError and the strum::EnumString derive of RedisError.
11. _this_value of JSValkeyClient::send and the this_js arguments that fed it.
12. ValkeyClient.connection_strings. Built, cloned by duplicate(), never read. The three strings it backed are now boxed directly, with the same contents.

Password hashing (src/runtime/crypto)
13. bcrypt::Params.silently_truncate_password and bcrypt::VerifyOptions. The value is true at both call sites and was read only by two debug_assert!s of that value.
14. pwhash::Encoding and the two HashOptions.encoding fields. Each has one value at its one call site, so the two InvalidEncoding returns cannot fire.

bun_core, crash handler, watcher
15. USE_SIMDUTF and LIBDEFLATE_SUPPORTED. Both are env::IS_NATIVE, which is true on every target that is not wasm. The scalar fallbacks in unicode.rs go.
16. DumpStackTraceOptions.skip_stdlib, skip_file_patterns, skip_function_patterns and the frame-skipping block in write_stack_trace. No caller sets them.
17. kind, hash and parents of Watcher::remove_at_index, and its directory branch. All four callers pass Kind::File, _, 0, &[].

CLI (src/runtime/cli)
18. Eleven arms of tag_print_help (PatchCommand, OutdatedCommand, PackageManagerCommand and eight more) and pm_print_help. tag_print_help is reached only for tags with USES_GLOBAL_OPTIONS, and these eleven have it false. These commands print --help through CommandLineArguments::print_help.
19. bun upgrade: the SILENT const generic of get_latest_version (one instantiation, false, so it never returned Ok(None)), and the Option of Version::name() (always Some).

CSS (src/css, src/css_jsc)
20. Component::DefaultNamespace, QNamePrefix::ImplicitDefaultNamespace, SelectorParsingState::SKIP_DEFAULT_NAMESPACE and SelectorParser::default_namespace(), which always returned None. The other hash tags and flag bits keep their values.
21. Bun.color(): the local log was never written, so the error arm always returned null. The throw behind it goes, with ParseError::basic (that throw was its only caller).
22. 24 convert_via! lines with RGBA as source or target, and impl From<RGBA> for SRGB. Nothing invokes them.
23. BackgroundHandler::reset and TransitionHandler::reset. They assign None to fields that flush has already take()n.

Parser (src/ast, src/js_parser, src/js_printer)
24. ImportRecordFlags::WAS_ORIGINALLY_REQUIRE and the three branches that test it. Nothing sets the flag. The other bits keep their positions.

Install (src/install)
25. StartManifestTaskError. A copy of ForManifestError with the same two variants and the same conversion to crate::Error.
26. The Result of ResolverContext::resolve (no impl returns Err) and the json parameter of count and resolve (no impl reads it).

Not a port regression

For each flag or option that is never set (write, cache::Fs.stream, was_originally_require, defaultNamespace, macro_remappings, client_entry_wrapper), git grep on d4514457e8^ (the last tree with the Zig sources) shows the same picture: declared and read, never set.

Open pull requests

Verification

  • bun bd (debug, ASAN) links.
  • cargo check --workspace --all-targets on the host, and cargo check --workspace --target <t> for the 12 targets of scripts/rust-check-all.ts: no error.
  • cargo check --workspace --all-targets --release (with the release codegen) and cargo clippy --workspace --no-deps: no error.
  • cargo fmt --all --check: clean.
  • Tests with the debug build, 0 failures: test/js/bun/css/css.test.ts (1314 pass), color.test.ts (1022), four selector and loader files in test/js/bun/css (39), test/bundler/css (3 files, 17), test/js/bun/util/password.test.ts (76), test/bundler/transpiler/transpiler.test.js (238), macro-test.test.ts (28), test/bundler/bundler_bun.test.ts (12), test/js/bun/resolve/resolve.test.ts (100), test/cli/install/bun-add.test.ts (221), test/cli/hot/hot.test.ts (16), test/js/valkey/valkey.test.ts (61, the rest needs Docker), test/internal/source-lints (182, three of them need more than the default 5 s timeout on a debug build).
  • test/bundler/bundler_edgecase.test.ts: 182 pass. One test, edgecase/DeepImportDiamondDAG, gives a 20,000-module build 60 seconds. The debug build needed 46 to 70 seconds on my machine, which depends on the load, so that test passed on the second run.
  • Valkey against a local Redis, debug build and 1.4.3 side by side: set, get, incr, hmset, hmget, sadd, send, a WRONGTYPE server error, 50 pipelined commands, duplicate() with subscribe, publish and unsubscribe, and a command on a dead connection. Same output.

Self-review

  • A self-review of the diff ran for about four hours and was stopped before it produced a verdict.

How the candidates were found

  • 23 read-only passes, one per area, looked for write-only state, functions with no effect, dead parameters, unreachable branches and dead stores. Each candidate was checked again before the edit and again in the diff.
  • Three compiler-level scans ran first and found nothing that an open PR does not already hold: a name index over all 3,203 Rust files, hawk (dead_public) and hawk --fix followed by rustc's dead_code.

Leads, not applied

  • src/css/prefixes.rs and src/css/compat.rs (generated by build-prefixes.js): 88 and 103 Feature variants are never constructed, about 1,900 lines with their arms and rows. They belong to lightningcss handlers that are not ported yet, so this needs the owner's decision.
  • Global::configure_allocator is an empty function with five call sites. Its comment says it is kept on purpose.
  • LinkerContext::check_for_memory_corruption has an empty body and 7 call sites. Its comment says it waits for the graph heap to become a MimallocArena.
  • LinkerOptions.mode is always Bundle (a lead of Remove dead code from bun_bundler, the JS parser, the help command, and PackageJSONEditor #44687 too). The removal re-indents about 130 lines of convertStmtsForChunk.rs, a file that many open PRs touch.
  • node::util::validators::validate_number and validate_array: the min, max and min_length arguments are None at every call site. They mirror Node's validators.
  • E::RegExp.flags_offset is write-only. Its removal leaves a length check in react_compiler/codegen.rs with no purpose, so it needs a decision there.

…client, and six smaller areas

Each removed line cannot run or holds a value that nothing reads:
options that only ever hold their default, hooks with an empty body,
parameters with one value at every call site, and results that are
never an error. No behaviour changes.
@robobun

robobun commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 9:00 AM PT - Oct 17th, 2026

✅ @robobun, your commit 65603939a444750aad1d3cda4fa22d23f53290b9 passed in Build #127450! 🎉


🧪   To try this PR locally:

bunx bun-pr 45723

That installs a local version of the PR into your bun-45723 executable, so you can run:

bun-45723 --bun

@robobun

robobun commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator Author

Status: ready for review.

How each removal was confirmed:

  • A search over src/, packages/ and the generated code shows every writer, reader and caller of the item (the PR body lists the 26 items).
  • cargo check --workspace passes for the 12 CI targets without the removed lines. bun bd, cargo clippy and a release-profile check pass too.
  • The tests listed in the PR body pass with the debug build.
  • No removed line is also removed by an open dead-code pull request.
  • The merge of this branch with main at ad4089bf49 has no conflict. cargo check --workspace passes on that merge for Linux x64, Windows x64 and macOS arm64.

CI on 65603939a4 is green. All 181 Buildkite jobs passed.

@robobun
robobun marked this pull request as ready for review October 17, 2026 11:08
@coderabbitai

coderabbitai Bot commented Oct 17, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 2 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: oven-sh/bun/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: a761679a-fe6c-44b0-a5eb-0b8def987ab1
📥 Commits

Reviewing files that changed from the base of the PR and between 017b243 and 6560393.

📒 Files selected for processing: 57
  • src/ast/import_record.rs
  • src/ast/target.rs
  • src/bun_core/Global.rs
  • src/bun_core/feature_flags.rs
  • src/bun_core/string/immutable/unicode.rs
  • src/bun_core/util.rs
  • src/bundler/Chunk.rs
  • src/bundler/ServerComponentParseTask.rs
  • src/bundler/bundle_v2.rs
  • src/bundler/entry_points.rs
  • src/bundler/linker_context/MetafileBuilder.rs
  • src/bundler/linker_context/generateChunksInParallel.rs
  • src/bundler/linker_context/writeOutputFilesToDisk.rs
  • src/bundler/options.rs
  • src/bundler/transpiler.rs
  • src/crash_handler/lib.rs
  • src/css/error.rs
  • src/css/properties/background.rs
  • src/css/properties/transition.rs
  • src/css/selectors/parser.rs
  • src/css/selectors/selector.rs
  • src/css/values/color.rs
  • src/css/values/color_generated.rs
  • src/css_jsc/color_js.rs
  • src/install/PackageManager/PopulateManifestCache.rs
  • src/install/PackageManager/processDependencyList.rs
  • src/install/lockfile/Package.rs
  • src/install/resolvers/folder_resolver.rs
  • src/js_parser/scan/scan_imports.rs
  • src/js_printer/lib.rs
  • src/jsc/RuntimeTranspilerStore.rs
  • src/jsc/VirtualMachine.rs
  • src/jsc/hot_reloader.rs
  • src/options_types/schema.rs
  • src/resolver/fs.rs
  • src/resolver/lib.rs
  • src/resolver/resolver.rs
  • src/runtime/api/JSTranspiler.rs
  • src/runtime/bake/config/transpiler.rs
  • src/runtime/bake/dev_server/directory_watch_store.rs
  • src/runtime/bake/dev_server/finalize.rs
  • src/runtime/bake/dev_server/watch.rs
  • src/runtime/cli/exec_command.rs
  • src/runtime/cli/mod.rs
  • src/runtime/cli/run_command.rs
  • src/runtime/cli/upgrade_command.rs
  • src/runtime/crypto/PasswordObject.rs
  • src/runtime/crypto/pwhash.rs
  • src/runtime/jsc_hooks.rs
  • src/runtime/valkey_jsc/ValkeyCommand.rs
  • src/runtime/valkey_jsc/js_valkey.rs
  • src/runtime/valkey_jsc/js_valkey_functions.rs
  • src/runtime/valkey_jsc/protocol_jsc.rs
  • src/runtime/valkey_jsc/valkey.rs
  • src/sys/fd.rs
  • src/valkey/valkey_protocol.rs
  • src/watcher/Watcher.rs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review found no issues

No high-confidence issues detected in this change.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants