Skip to content

Remove dead code from Progress, Tag::infer, bun_jsc::Error and SignResult - #45974

Open
robobun wants to merge 7 commits into
mainfrom
robobun/9b78bd75/dead-code-sweep
Open

robobun wants to merge 7 commits into
mainfrom
robobun/9b78bd75/dead-code-sweep

Conversation

@robobun

@robobun robobun commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

Behaviour change: none

Problem

  • Four items cannot run, or hold a value that nothing reads. Progress.dont_print_on_dumb is false in every Progress. Tag::infer makes two hosted-git lookups that cannot change its answer. Five variants of bun_jsc::Error are never constructed. SignResult.request_payer is written and never read.
  • rustc does not report them. Its dead_code lint skips pub items and counts an assignment to a field as a use.

Fix

  • Delete them: 43 lines removed in 4 files, none added.
  • Correct because no code on main reads, sets or constructs them, and the 12 CI targets compile without them.
  • Verified on this head: bun bd, cargo check --workspace, cargo clippy, cargo fmt --check, 5 test files. bun run rust:check-all and --all-targets ran on the head before the merge of main (Notes).
  • Self-reviewed: 22 concerns raised, 22 addressed. The first push removed 435 lines: the rest collides with open pull requests (Notes).

Background

  • Tag::infer classifies a dependency specifier. For a git:// or git+http(s):// URL it also asked HostedGitInfo::from_url. hgi_to_tag maps that result to Tag::Github only for a shortcut such as github:user/repo, which these URLs never are. Every other result is Tag::Git, which the next statement returns.
  • No other design was weighed: a deletion has one place.

Downsides

  • None found. Checked: a trial merge with each other open pull request adds no conflict, and none uses a removed name (Notes).
Notes

Removed

  1. bun_core::Progress.dont_print_on_dumb (src/bun_core/Progress.rs): the field, its default, and the early return in refresh_with_held_lock that tests it. No code sets it, so it is false in every Progress. The last tree with the Zig sources (d4514457e8^) never set it either.
  2. Tag::infer in src/install/dependency.rs: the two HostedGitInfo::from_url lookups for git:// and git+http(s):// inputs.
    • hgi_to_tag returns Tag::Github only when the representation is Shortcut.
    • from_url gives Shortcut only for the protocols github:, gist:, gitlab:, bitbucket: and sourcehut:, or for a user/repo shorthand.
    • is_github_shorthand rejects an input with a : before a #, and normalize_protocol reads git:, git+http: or git+https: from these inputs.
    • So the lookup gives Tag::Git or fails, and both cases reach return Tag::Git.
  3. Five variants of bun_jsc::Error that nothing constructs (src/jsc/error.rs): InvalidDataURL, InvalidURL, TarballFailedToExtract, MissingDebugInfo, EndOfFile, with their name() arms. Other crates have variants with the same names in their own Error enums. The enum has no repr and no conversion from a number or a string.
  4. bun_s3_signing::SignResult.request_payer (src/s3_signing/credentials.rs): the field, its default and its one store. sign_request writes the x-amz-request-payer header from its local of the same name.

Open pull requests

  • Compared at 2026-10-18 23:00 UTC with the heads of all 5,680 other open pull requests, drafts and every author included. Compared again at 2026-10-20 12:50 UTC with the 607 open pull requests that changed after the first comparison, and at 2026-10-21 20:50 UTC with the 604 that changed after the second.
  • A trial merge of each head with main and with this branch (git merge-tree) shows that the branch adds no conflicted file and no conflict hunk.
  • None adds a use of a removed name. The added lines of every head were searched for dont_print_on_dumb, request_payer on a SignResult, and the five variant names in bun_jsc.
  • The second comparison found one new collision, Build every runtime ES module's record from the transpiler output instead of a second JSC parse #35605, and that item went back (see below).

Found dead in this run, and left alone

The first push of this PR removed 24 items (435 lines). My check of the open pull requests was too weak then: it compared only the lines that they remove or change. The trial merge above, run for that first head, adds a conflicted file to 32 open pull requests (11 of them merge clean today) and more conflict hunks to 20, 49 pull requests in total. Open pull requests also use eight of the removed items. Each item below has no reader or constructor on main and compiled away on 12 targets. A later run can take it when its blocker lands or closes.

An open pull request uses the item:

The removal adds a merge conflict to an open pull request:

How the candidates were found

  • A probe build. In a scratch copy, struct fields got a unique #[deprecated] tag, and cargo check --workspace for Linux, Windows and macOS listed every use site. A field with only initializer and assignment sites is write-only.
  • The tagger has a defect: it skips the field after each field that it tags. It tagged 16,242 of about 28,500 fields, so about 43% of the fields were never probed. Two untested neighbours of items above are BundleOptions.debugger and SignResult.storage_class.
  • A read-only audit of 51 units of about 10,000 lines each, for write-only state, parameters with one value, results that cannot fail and variants that nothing constructs. Two more readings tried to refute each finding, also against the last Zig tree.
  • Also dry: a relink of the debug binary with --gc-sections --print-gc-sections (131 unreachable C-linkage functions, 101 of them already in open pull requests, the rest platform code), clang with -Wunused-function over the C++ bindings, files in no mod tree or build target, unused Cargo dependencies.

Leads, not applied

State with a missing reader or writer. The audit reported these, and I did not verify them:

  • virtual_machine::Options.dns_result_order is set for compiled executables and never copied into the VM. Forward --inspect and --dns-result-order to the VM in compiled executables #40703 is open for it.
  • bunfig [debug].editor is stored and never read. Bun.openInEditor: use the [debug] editor setting from bunfig.toml #38059 is open for it.
  • js_parser: the deferred await and yield errors of arrow arguments go into a copy that is thrown away.
  • js_parser: PropertyOpts.declare_range is never set.
  • ParseResult.pending_imports is always empty, so nothing feeds the AsyncModule queue.
  • Bun.build: Config.dir and Config.css_chunking are never set from JS. bun:ffi cc(): library_dirs is never assigned. bunfig [bundle].packages is stored and never read.
  • extract_blob in spawn/stdio.rs compares the stdio slot index with itself.

Unfinished work, not dead code: P::keep_expr_symbol_name returns its argument unchanged. It is the --keep-names hook, and #40503 implements that feature.

The same class as ModuleInfo::finalize, for a later run: Stdio::as_spawn_option, Log::clone_to_with_recycled, and the StreamBuffer and ByteVecExt writes never return Err. JsSinkType::HAS_FLUSH_FROM_JS is true in all six impls. Stdio::Memfd exists only as stdin. Open pull requests edit the same lines (#42819, #43896, #44301, #44493, #45591, #43709, #43737).

Verification

  • On this head (0f2f9e3, after a merge of main at ea6a2c7): bun bd, cargo check --workspace, cargo clippy --workspace --no-deps, cargo fmt --all -- --check.
  • On c2b7b22, which had these four items and the finalize item on top of 5900354: bun run rust:check-all (12 ok, 0 failed, 0 skipped (of 12)) and cargo check --workspace --all-targets. The 13 commits of main since then add no line that names a removed item.

Tests, debug build of this head

  • test/cli/install/hosted-git-info/from-url.test.ts: 685 pass, 32 skip.
  • test/cli/install/bun-install-git-deps.test.ts: 201 pass, 1 skip.
  • test/cli/install/migration/yarn-lock-migration.test.ts: 69 pass.
  • test/cli/install/bun-add.test.ts: 219 pass.
  • test/js/bun/s3/s3-requester-pays.test.ts: 10 pass.

no test proof · iteration 0 · the description declares no behaviour change, so there is no failing test to prove; the existing suite in CI is the check

@robobun

robobun commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 11:32 AM PT - Oct 20th, 2026

✅ @robobun, your commit 0f2f9e31839015a7c586bdf134b2ee0280903472 passed in Build #129533! 🎉


🧪   To try this PR locally:

bunx bun-pr 45974

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

bun-45974 --bun

@robobun

robobun commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator Author

Status: ready for review. CI is green.

  • This PR deletes code that cannot run or that nothing reads, so there is no repro. The PR body lists each of the four items with its proof.
  • CI: build 129533 passed on the branch head 0f2f9e3 (181 of 181 jobs).
  • Checked locally on that head: bun bd, cargo check --workspace, cargo clippy, and the five test files that the Notes list.
  • A trial merge with the heads of the other open pull requests adds no conflict, and none of them uses a removed name. Last comparison: 2026-10-21 20:50 UTC, with main at 491aaad.

@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.

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Beyond the inline comment, I also checked a few of the deletions for hidden behaviour changes and found none: both register_for_epoll callers passed one_shot=true and the Flags::OneShot reads that remain are on the separate posix_event_loop flag set; HostedGitInfo::from_url on git:///git+http(s):// input never yields a Shortcut representation, so hgi_to_tag could only return Tag::Git; and Bits::drain in the GIF decoder only advanced a cursor that decode_frame returns without reading.

Extended reasoning...

Dead-code sweep across 40 Rust files plus one C++ extern removal, with no security-sensitive surface touched (the cron.rs changes only drop unreachable OOM arms around infallible Vec writes). The one posted finding is a stale SAFETY comment in linker.rs that still names the deleted preserve_extensions field; the ruled-out items above were re-verified from the code rather than the PR description.

Comment thread src/bundler/options.rs
@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: oven-sh/bun/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 417944ef-a655-43cd-a23c-6a8e34bbcc8c
📥 Commits

Reviewing files that changed from the base of the PR and between c2b7b22 and 0f2f9e3.

📒 Files selected for processing: 1
  • src/install/dependency.rs
💤 Files with no reviewable changes: 1
  • src/install/dependency.rs

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review.

Walkthrough

The pull request removes a progress option and several public error variants. Git dependency inference no longer looks up hosted-provider metadata for specified URL forms. S3 signing results no longer store the requester-payer option.

Changes

Progress Rendering

Layer / File(s) Summary
Progress refresh behavior
src/bun_core/Progress.rs
The dont_print_on_dumb field and default are removed. Refresh no longer returns early based on that option. It continues to the terminal-presence check.

Git Dependency Tag Inference

Layer / File(s) Summary
Git URL tag selection
src/install/dependency.rs
For git:// and recognized git+http(s):// URLs, inference no longer uses hosted-provider metadata to select a tag. Non-GitHub-shorthand URLs return Git.

Public Error Variants

Layer / File(s) Summary
Error variants and name mappings
src/jsc/error.rs
The Error enum removes InvalidDataURL, InvalidURL, ParserError, TarballFailedToExtract, MissingDebugInfo, and EndOfFile. The ParserError name mapping remains.

S3 Signing Result

Layer / File(s) Summary
Requester-payer result field
src/s3_signing/credentials.rs
SignResult no longer stores or initializes request_payer. Signed-request construction still generates the requester-payer header.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to 0f2f9

This change removes unused code and has no stated behavior change. No concrete merge-blocking risk was identified from the supplied context.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title concisely and accurately summarizes the main changes across Progress, Tag::infer, bun_jsc::Error, and SignResult.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The description explains the problem, the four removals, verification steps, risks, and background. It does not use the exact template headings, and it states that five bun_jsc::Error variants were …
Full details: Description check

Explanation

The description explains the problem, the four removals, verification steps, risks, and background. It does not use the exact template headings, and it states that five bun_jsc::Error variants were removed while the change summary lists six, including ParserError. These are minor clarity issues because the required information is otherwise present.

  • 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.

Comment thread src/bun_core/string/mod.rs Outdated
Comment thread src/js_printer/lib.rs Outdated
@robobun

robobun commented Oct 18, 2026

Copy link
Copy Markdown
Collaborator Author

The review found one stale comment: the SAFETY comment of Linker::options named preserve_extensions, which this PR deletes. f43c374 names rewrite_jest_for_tests in its place, the other field that the one caller reads.

341e416 answers the two comment-length notes: the doc comment of js_printer::Encoding is one line now, and the one on bun_core::printer::write_pre_quoted_string is back to its text from main.

No code changed in these two commits. The diff is now 41 files, +93 and -435 lines.

@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.

I re-reviewed the current head after the follow-up commits and found no bugs; the stale preserve_extensions reference in the Linker::options SAFETY comment is now updated. Because this sweep spans 41 files including macOS/Windows-only cron paths and Linux epoll code that cannot be type-checked from one target, a human look is still worthwhile.

What was reviewed:

  • Tag::infer git-URL fallback: traced HostedGitInfo::from_url → hgi_to_tag; Representation::Shortcut (the only path to Tag::Github) requires a github:-style protocol, which git:///git+http(s):// inputs never produce, so Tag::Git is the only outcome.
  • Flags::OneShot removal in src/io/lib.rs: the remaining Flags::OneShot hits are on the separate posix_event_loop::Flags enum; register_for_epoll is pub(crate) with only the two true callers.
  • Grepped the whole tree for Bun__allocUint8ArrayForCopy, IS_MAIN_THREAD_VM, ImportWatcher::None, ArrayBuffer::alloc::<, the removed jsc::Error variants and strings::Encoding::{Ascii,Utf16} — no remaining references (the Encoding::Utf16 hits are the separate js_printer, bun_ast::e::StrEncoding and StandaloneModuleGraph enums).
  • codec_gif Bits::drain, ansi_renderer src/title restores (fields are .take()n before), the non-Windows drop(iter) in prune.rs, and the node_fs did_succeed/phase locals: confirmed nothing reads the removed state afterwards.
Extended reasoning...

The change is a dead-code removal sweep across 41 files (+93/-435): write-only struct fields, never-constructed enum variants, infallible functions losing Result wrappers, a thread-local, one C++ export, and an always-true epoll parameter. It touches no auth, crypto, or input-validation logic; the s3_signing change only drops two unread SignResult fields and the cron.rs changes only remove unreachable OOM arms. Every removal I could trace statically checks out as dead, and the one nit from the prior review was addressed in f43c374. Deferral rather than approval is because of the size and the amount of cfg-gated macOS/Windows/Linux-only code whose compilation I could not verify here; no CODEOWNERS entry covers the changed files and no third-party objection is open.

@robobun
robobun marked this pull request as draft October 18, 2026 22:42
@robobun

robobun commented Oct 18, 2026

Copy link
Copy Markdown
Collaborator Author

I moved this PR back to draft. Do not merge the current head (341e416).

A review of the diff against the heads of the open pull requests found that some of the removed items are used by open work. My first check compared only the lines that open PRs remove or change. It did not search the lines that they add, and it did not run trial merges.

Open PRs that use an item this PR removes (each one merges without a conflict and then does not compile):

Removals that add a merge conflict to open PRs: the parser's Options.transform_only (#44833, #45415, #45557, #44687), one_shot and Flags::OneShot in bun_io (#44293), BundleOptions.preserve_extensions (#36757), SignResult.acl (#45440), EventLoop.waker (#42819).

I will put these items back on this branch, run the checks again, check the trimmed diff with a trial merge against every open PR head, and then rewrite the description.

@robobun robobun changed the title Remove dead code: write-only fields, state that never changes, error arms that cannot run Remove dead code from Progress, ModuleInfo::finalize, Tag::infer, bun_jsc::Error and SignResult Oct 19, 2026
@robobun
robobun marked this pull request as ready for review October 19, 2026 01:49

@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.

LGTM — the trimmed-down removal set is behavior-preserving; each deletion checks out against the code.

What was reviewed:

  • Traced Tag::infer's dropped HostedGitInfo::from_url fallback: for git:// and git+http(s):// inputs, normalize_protocol yields Git/GitPlusHttp(s), is_github_shorthand rejects on the early :, and correct_url can only produce GitPlusSsh, so Representation::Shortcut (the only route to Tag::Github) is unreachable and the result was always Tag::Git.
  • Read ModuleInfo::finalize end to end: no ? or Err, so the three dropped error arms (Alloc mapping, None return, module_info = None; continue) could not run.
  • Confirmed the remaining MissingDebugInfo/EndOfFile uses in src/jsc/btjs.rs are bun_crash_handler::Error, and the "InvalidDataURL"/"TarballFailedToExtract" string matches in ResolveMessage.rs/AsyncModule.rs come from bun_install::Error::name(), not the removed bun_jsc variants.
  • Checked SignResult.request_payer readers (only the sign_request local and the cache-key struct) and dont_print_on_dumb (no setter anywhere in the repo).
Extended reasoning...

The change is a pure deletion (+4/-58) across six Rust files: a write-only Progress flag and its early-return, an infallible Result wrapper on ModuleInfo::finalize plus its three dead error arms, two always-equivalent hosted-git lookups in Tag::infer, five never-constructed bun_jsc::Error variants, and a write-only SignResult field. It touches the S3 request-signing file but only removes a field that is written and never read; the x-amz-request-payer header emission still reads the local variable and the credentials/options structs keep their own field. Every claimed-dead item was verified by grep and by reading the hosted_git_info parsing path, so there is no behavior change to test. The diff has shrunk substantively since the earlier reviews (later commits restored items colliding with open PRs, mooting the earlier SAFETY-comment nit), no CODEOWNERS entry covers these files, and no CHANGES_REQUESTED review is outstanding.

@robobun

robobun commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator Author

The trim is done, and the PR is ready for review again at c2b7b22. The title and the description now describe this head.

  • The diff is 6 files, 4 lines added and 58 removed. Five items stay: Progress.dont_print_on_dumb, the Result of ModuleInfo::finalize, two lookups in Tag::infer, five variants of bun_jsc::Error, and SignResult.request_payer.
  • I ran a trial merge (git merge-tree) of each of the 5,680 other open pull request heads with main and with this branch. The branch adds no conflicted file and no conflict hunk. I also searched the added lines of every head: none uses a removed name.
  • The same two checks on the first head of this PR (341e416) show a new conflicted file in 32 open pull requests and more conflict hunks in 20. Every item that collides is back in the tree. The Notes list each one with the pull requests that block it.
  • Checks on this head: bun bd, bun run rust:check-all (12 of 12), cargo clippy, cargo check --workspace --all-targets, and nine test files.

@robobun robobun changed the title Remove dead code from Progress, ModuleInfo::finalize, Tag::infer, bun_jsc::Error and SignResult Remove dead code from Progress, Tag::infer, bun_jsc::Error and SignResult Oct 20, 2026
@robobun

robobun commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator Author

I merged main (ea6a2c7) into the branch and took one more item out. The head is now 0f2f9e3: 4 files, 43 lines removed, none added.

  • The item that went back is the Result of ModuleInfo::finalize. Build every runtime ES module's record from the transpiler output instead of a second JSC parse #35605 changed after this PR opened: it now adds a caller that tests that Result, and it edits the function. The Notes list the item with the others that wait for an open pull request.
  • I compared the branch again with the 607 open pull requests that changed since the first comparison. A trial merge adds no conflict for the four items that stay, and none of those pull requests uses a removed name.
  • The 13 commits of main since the old base add no line that names a removed item. On the merged head, bun bd, cargo check --workspace and cargo clippy pass, and the five test files in the Notes pass.
  • The last CI run (build 128667, on the old head) had two red jobs, and neither is from this diff: an artifact download that timed out on the darwin aarch64 test lane, and the bake.test.ts restart tests that also flake on main.

@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.

LGTM — since the last review the branch merged main and put ModuleInfo::finalize back, leaving a 43-line deletion-only diff across four files, and each removed item checks out as dead.

What was reviewed:

  • Tag::infer: traced HostedGitInfo::from_url → hgi_to_tag for git:// and git+http(s):// input; Representation::Shortcut only arises from a shortcut protocol or is_github_shorthand, which rejects any input with a : before #, and correct_url can only yield GitPlusSsh, so the removed lookups could never return Tag::Github.
  • bun_jsc::Error variants: grepped for Error::, CrateError:: and bun_jsc::CrateError:: constructors/matches workspace-wide; the only MissingDebugInfo/EndOfFile hits are in btjs.rs, which imports bun_crash_handler::Error, and ResolveMessage.rs/AsyncModule.rs match on name() strings sourced from the resolver/install enums.
  • SignResult.request_payer (pub(crate)) has no reader in src/s3_signing; the x-amz-request-payer header is still emitted from the local. dont_print_on_dumb has no reference anywhere in the repo, and both Progress literals use ..Default::default().
  • Minor: the PR description still says 58 lines in 6 files including finalize; the diff is now 43 lines in 4 files.
Extended reasoning...

The diff removes a never-set Progress field and its early return, two redundant HostedGitInfo::from_url lookups in Tag::infer, five never-constructed bun_jsc::Error variants, and a write-only SignResult.request_payer field. It touches S3 request signing, but only by dropping a field that nothing read; the header emission path is unchanged, and no struct involved is repr(C) or mirrored in C++. The bug hunt ran dry, no CODEOWNERS entry covers these files, and the timeline shows no CHANGES_REQUESTED review; the commits since the last bot review narrowed scope (reverted the finalize change) rather than adding risk. Each deletion was independently confirmed dead by grep and by tracing the hosted-git-info protocol/representation logic, which is what decided approve.

@robobun

robobun commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator Author

A note on the automated summary above: it lists six removed variants of bun_jsc::Error, with ParserError among them. The diff removes five. ParserError stays in src/jsc/error.rs at the head (0f2f9e3), the variant and its name() arm, because #42671 constructs it. The description is correct as it is.

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