Repository navigation
Conversation
|
Updated 7:34 PM PT - Oct 15th, 2026
✅ @robobun, your commit 5d917dc57ba746ff19a17fa8378e6a0b498841b4 passed in 🧪 To try this PR locally: bunx bun-pr 45430That installs a local version of the PR into your bun-45430 --bun |
|
Status: ready for review. CI is green. How the deletions were verified:
CI:
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
WalkthroughThe change removes an AST conversion implementation and several trait implementations used in semantic analysis. The ChangesImplementation removals
Priority: ⬇️ Low Merge Risk: ⚪ Minimal · up to
|
There was a problem hiding this comment.
LGTM — a pure deletion of six trait impls, and each one checks out as unreferenced.
What was reviewed:
AsAstNodes for Class: the trait ispub(crate), has no generic bounds anywhere insrc/format, andClassis not in anyformat_with_comments!invocation; every.as_ast_nodes()call site is on another handle.From<Atom> for u32: the onlyInto<u32>bounds insidebun_semaareFile::listandNodeKey for (FileId, I);IdList<Atom>is built from raw.0fields inparser/ty.rsand read viaFrom<u32>, and noByKey/IdMapis keyed byAtomwith that bound.MaybeLocal for ()/u8andPacked for u8: enumerated everyByKeykey type (ID tuples,Atom,Node,relate::Key,IntersectionKey) and everyById/ByNodevalue type — none contains a bareu8or(), andByKeyputs noPackedbound on its value, sorelations: ByKey<_, u8>is unaffected.Follow for Box<T>: every boxed field in afollow_struct!/follow_enum!type or manualFollowimpl is anArenaBox, which keeps its own impl.
Extended reasoning...
The change is a 46-line deletion across five Rust files in bun_sema and bun_format, removing six trait impls with no additions and no behavior change for any surviving call site. It touches no security-sensitive surface (no parsing of untrusted input, auth, or crypto). It was approved because each removed impl was independently traced by grep to zero users: the format trait is crate-private, the sema traits are only bounded inside bun_sema, and the concrete key/value types that could have needed the deleted impls were enumerated and found not to. No CODEOWNERS entry covers the changed paths and the timeline shows no outstanding objections.
Problem
bun_semaandbun_formathave no caller and no bound that needs them.dead_codelint and mordant'sunused_pubdo not check trait impls.Fix
--gc-sectionskeeps no function of these impl blocks, and the workspace compiles without them.cargo check --workspace --all-targets,rust:clippy,rust:mordant,rust:check-all(12 targets),bun bd,test/cli/format/format.test.ts,test/cli/check/check.test.ts.T: Spannedbounds (a decision for its owner).Background
--gc-sectionsdrops each function that has no caller. That proves linux.cargo checkcovers the other targets.Spannedimpls of the formatter. This diff shares no file with them.Downsides
cargo checkfor 12 targets.Behaviour change: none
Notes
Removed impls, by file
src/format/js/ast_nodes.rsimpl<'a> AsAstNodes<'a> for Class<'a>src/sema/hir.rsimpl From<Atom> for u32src/sema/local.rsimpl MaybeLocal for ()impl MaybeLocal for u8src/sema/table.rsimpl Packed for u8src/sema/types.rsimpl<T: Follow> Follow for Box<T>Candidates that stayed
#[inline(always)]function, which has no symbol of its own at opt-level 0, so the link says nothing about them. 34 areDebug(a debugging aid, kept as in Remove dead code: 49 trait impls nothing uses, across 12 crates #43664) and 15 areDrop. None of these are in this diff.Spannedimpls of the formatter andDefault for Session. I dropped them from this branch.Spannedimpls of the formatter that bound sits on a function that never calls.span(), see the follow-ups.Display for Difference(src/format/verify.rs): a public diagnostic type of--debug-check.From<Vec<Doc>> for Doc(src/format/css/doc.rs): thedocs!macro documents "anything that can be made a document" as its input.PathCharCwd for u16(src/node_path/lib.rs): the Windows path character.ExtendandFromIteratorforIdMapandClone for IdBitSet(60 files use them),From<Vec<T>>,Into<Box<[T]>>andPartialEq<Vec<T>>in both directions for the semaList(141 files), andFrom<BabyVec>,AsRef,Borrowand twoIntoIteratorimpls forArenaBox.bun_lint:HashforCodePath,Segment,EsNode,Reference,SignatureandTsSymbol,FromforTarget,TokenOrText,ValueandDeclarationKinds, andLocated,LocateandStaticallyNamedfor some handles. They are the surface that rule ports use, and the trait docs describeLocateandLocatedas a table of handles. They stay for the owners of the lint crates to decide.Method details
build.ninjaplus-Wl,--gc-sections -Wl,--print-gc-sections. The export list and the version script stay, so the NAPI, V8 and uv surface is still a root.llvm-nmlists the 1,179,735 kept function symbols of the relinked binary andllvm-symbolizermaps each tofile:line. An impl block is a candidate when no kept address falls inside it.cargo check --workspace --keep-going --message-format=json, put back each impl that an error names, repeat until clean. Then the same with--all-targets.src/format,src/semaorsrc/react_compiler. Remove dead code from bun_format, bun_sema, bun_install, and bun_core #45402, Remove dead code from bun_format and napi.cpp #45420,bun lint --stagedandbun fmt --stagedread what is staged #45403,bun lint: warn when a tsconfig.json withoutincludemade it load many files to lint a few #45302, bundler: keep a read off a require() / import() local a property access until the linker binds it #45296, react-compiler: decode a UTF-8 string when constant propagation joins it to a UTF-16 string #45172, fix(check): unify project ownership across paths and globals #45131, fix(check): preserve narrowed unions and mapped recursion identities #45130 andbun check: refuse paths that have no TypeScript file #44764 merged with this branch passcargo check --workspace. Bun.highlight: syntax highlighting to HTML and ANSI, on the formatter's parsers #45208, perf(sema): avoid quadratic JSON object conversion #44996 andbun check <file>: check a file in the referenced project that lists it #44900 conflict with main on their own, in files this diff does not touch, and the Rust lines they add name none of the 6 impls or their traits.test/cli/format/format.test.ts1015 pass, 0 fail (with--timeout 120000, the ASAN build is slow).test/cli/check/check.test.ts592 pass, 1 fail: "the client that Eden Treaty infers from an Elysia app" needstest/node_modules/@elysia/eden, which this machine does not have.bun lint: categories skip frameworks the project doesn't use, and"plugin/*" = "off"turns a plugin off #45297) touchessrc/lintand tests only.Self-review, the six concerns
bun fmt: every comment is attached to one node before printing, as in Prettier #45205 orphaned theSpannedimpls. That holds for three of them only, and none of those is in this diff. The claim is gone.Packed for u8had been kept by a loose match in the restore loop. It compiles away, so it is in.Default for Session"for clippy".new_without_defaultis allowed inCargo.toml, and Remove dead code from bun_format, bun_sema, bun_install, and bun_core #45402 removes the impl.+ Spannedbounds. That changes what a generic function accepts, so it is a decision for the owner of the formatter. It is the first follow-up below.Other scans in this run, clean or already claimed
.rsfiles outside every mod tree: none in 121 crates.#[no_mangle]exports that the link drops: 31 exports. Each one is in an open PR or has a caller on macOS or Windows.externdeclarations with no caller: 3. Two are in open PRs.SSL_set0_verify_cert_store(src/boringssl_sys/boringssl.rs, one line) is left for a run that touches that crate.cfg(windows)(LTO inlines it, so the Windows map does not list it), is anALWAYS_INLINEhelper that a WTF template calls by name, or is support code for a type thatsrc/codegen/bindgen.tscan emit (IDLByte,IDLShort,IDLLongLong, the clamp and enforce-range adaptors).tsc --noUnusedLocalsoversrc/js,src/codegen,scriptsand the bake client: only unused parameters, and locals that Remove the dead code from the bake error overlay syntax highlighter #44514 removes.src/js/builtins/BunBuiltinNames.h,bun:internal-for-testingexports,macro_rules!macros with no invocation, scripts that nothing names: nothing unclaimed.Follow-up candidates, not in this diff
+ Spannedbounds of the formatter sit on code that never calls.span():speculate_will_breakandJoinBuilder::entries_with_trailing_separator(src/format/js/builders.rs:90,:104),Format for FormatSpecifiers(print/import_declaration.rs:155),FormatNodeWithoutTrailingComments(utils/format_node_without_trailing_comments.rs:6) andwrite_part_before_keyword(print/try_statement.rs:13).Spannedimpls that nothing calls exist to satisfy them. One example isWithSpan<T>inutils/assignment_like.rs, a wrapper that only carries a span forspeculate_will_break. The bounds can also be read as a guard that the content is a node, so the owner of the formatter decides.PerformanceResourceTimingis never constructed on any platform:PerformanceResourceTiming::createhas no caller andperformance.markResourceTimingis a stub. About 1,100 lines are behind it (ResourceTiming,NetworkLoadMetrics,ResourceLoadTiming,ServerTiming,PerformanceServerTiming::create). The two global constructors are tested API (test/js/web/web-globals.test.js,perf_hooks), so the removal is a rewrite of the wrappers and needs a maintainer decision.toJSNewlyCreatedforCloseEvent,CustomEvent,ErrorEvent,MessageChannel,TextEncoderandURLPattern, with theENABLE(BINDING_INTEGRITY)vtable declarations above each, has no caller. Each one is next to thetoJShunk of Remove dead code from the WebCore bindings, the JSSink codegen, and two Rust helpers #39929.WEBCORE_GENERATED_CONSTRUCTOR_GETTERinZigGlobalObject.cppdefines a<Class>_getterfor 48 classes. 12 are used.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