Repository navigation
clippy: unbreak cargo clippy on main (let_and_return + large_stack_frames) - #33951
Conversation
#33874 removed the `if cfg!(debug_assertions) && is_windows { debug_assert!(..) }` block that sat between the binding and the return, leaving let result = &mut buf[0..buf_i]; result which `clippy::let_and_return` rejects under `-D warnings`. The Clippy workflow only runs on `pull_request` and `merge_group`, never on a push to main, so main does not lint itself and this surfaces on every open pull request that touches a .rs file — `pull_request` lints the merge ref. Return the slice directly.
|
Updated 7:09 PM PT - Jul 10th, 2026
@cirospaciari, your commit e9d5087 is building: |
WalkthroughThe changes simplify a path normalization return and add a targeted Clippy allowance to runtime initialization. ChangesPath normalization
Runtime lint handling
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Comment |
There was a problem hiding this comment.
LGTM — mechanical clippy fix with zero behavioral change.
What was reviewed:
- Confirmed
let result = &mut buf[0..buf_i]; result→&mut buf[0..buf_i]is semantically identical; the binding had no other use after #33874 removed the interveningdebug_assert. - Checked that
ZERO_TERMINATEstill writes the NUL atbuf[buf_i]before the returned slice is taken — unchanged. - No CODEOWNERS entry for
src/paths/.
Extended reasoning...
Overview
Single-file, 3-lines-to-1-line change in src/paths/resolve_path.rs at the tail of normalize_string_generic_tz. It replaces let result = &mut buf[0..buf_i]; result with the direct expression &mut buf[0..buf_i]. This is the exact transformation clippy's let_and_return lint suggests, and it became necessary after #33874 deleted the debug_assert that previously sat between the binding and the return.
Security risks
None. This is a syntactic refactor of a return statement in a path-normalization helper; no new inputs, no new control flow, no changed bounds. The slice range [0..buf_i] is computed identically to before.
Level of scrutiny
Minimal. The change is provably behavior-preserving by inspection — the two forms compile to the same thing. The PR description documents that clippy was reproduced failing on main and passes with the fix, plus test/js/node/path/ and vendored test-path*.js all pass, which is more verification than a lint fix strictly needs.
Other factors
- No CODEOWNERS coverage for
src/paths/. - No prior reviewer comments to address.
- The bug hunting system found nothing.
- The PR is already the tip of
mainin the checked-out repo (commit fe93867), so the change has effectively been validated in-tree. - The PR description's note about the macOS-only
derivable_implswarning and the missingpush:trigger onclippy.ymlare informational and correctly left out of this diff.
With bun_paths compiling again, clippy reaches bun_runtime and rejects
`init_runtime_state`:
error: this function may allocate 221049 bytes on the stack
--> src/runtime/jsc_hooks.rs:301:11
The frame is `bun_bundler::Transpiler::init`'s return value: a `Transpiler`
carries a `Resolver` whose `BSSMapInner<DirInfo, 2048>` is ~229 KB, and the
value is returned by move and then `ptr::write`n straight into
`(*vm).transpiler`. Optimized builds elide the copy, and the function runs once
per VM init.
Suppress it the same way `find_context_identifiers::walk_expr` does, with the
reason recorded. Removing the temporary for real means an in-place
`Transpiler::init_in_place(dst, ..)`, which is a larger change owned by the
bundler.
Only Linux crosses the 128 KB `stack-size-threshold`; macOS clippy does not
flag this function, so `#[allow]` (not `#[expect]`) — an expectation would go
unfulfilled there.
cargo clippy on main (let_and_return + large_stack_frames)
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/jsc_hooks.rs`:
- Around line 301-306: Replace the by-value Transpiler::init call in the VM
initialization path with Transpiler::init_in_place, constructing directly in
(*vm).transpiler. Remove the clippy::large_stack_frames allowance and update the
surrounding initialization logic to use the in-place API’s signature.
🪄 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: 67af85a0-c6a6-4f63-a90d-a777a9142f18
📒 Files selected for processing (1)
src/runtime/jsc_hooks.rs
| #[allow( | ||
| clippy::large_stack_frames, | ||
| reason = "`Transpiler::init` returns a Transpiler by value (~216 KB: its Resolver embeds \ | ||
| BSSMapInner<DirInfo, 2048>) and it is `ptr::write`n straight into `(*vm).transpiler`. \ | ||
| The copy is elided in optimized builds, and this runs once per VM init." | ||
| )] |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
Use Transpiler::init_in_place instead of suppressing this warning.
This allowance leaves the large by-value Transpiler temporary in place. The supplied src/bundler/transpiler.rs implementation provides init_in_place specifically to construct directly in VirtualMachine.transpiler; that avoids the large stack temporary and remains important for debug/ASAN builds, where optimized copy elision does not protect the stack budget. Remove the allowance and route this initialization through the in-place API.
🤖 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/jsc_hooks.rs` around lines 301 - 306, Replace the by-value
Transpiler::init call in the VM initialization path with
Transpiler::init_in_place, constructing directly in (*vm).transpiler. Remove the
clippy::large_stack_frames allowance and update the surrounding initialization
logic to use the in-place API’s signature.
There was a problem hiding this comment.
LGTM — two lint-only fixes with no runtime behavior change.
What was reviewed:
resolve_path.rs: inlineslet result = ...; result→ direct return; identical codegen.jsc_hooks.rs: adds#[allow(clippy::large_stack_frames, reason = ...)]matching the existing pattern atfind_context_identifiers.rs:380;#[allow]over#[expect]is correct since the lint is Linux-only perclippy.toml's stack-size-threshold.- Confirmed
large_stack_frames = "deny"in workspaceCargo.tomland no CODEOWNERS on either file.
Extended reasoning...
Overview
Two-file, lint-only PR unbreaking cargo clippy on main:
src/paths/resolve_path.rs: 3 lines → 1 line, removing an intermediatelet resultbinding whose only consumer (adebug_assert) was deleted in #33874. The returned expression&mut buf[0..buf_i]is byte-identical.src/runtime/jsc_hooks.rs: adds a 6-line#[allow(clippy::large_stack_frames, reason = ...)]attribute aboveinit_runtime_state. No code inside the function changes.
Security risks
None. Neither change alters control flow, data flow, allocation, or any value observable at runtime. The first is a pure syntactic refactor of a return expression; the second is a compile-time lint attribute.
Level of scrutiny
Low. These are the canonical shapes for their respective clippy fixes:
let_and_return→ inline the expression (clippy's own machine-applicable suggestion).large_stack_frames→ the repo already suppresses this identically atsrc/react_compiler/lowering/find_context_identifiers.rs:380-383. Thereason =string is accurate (verifiedTranspiler::initis called andptr::writen into(*vm).transpilerper the surrounding doc comment), and the choice of#[allow]over#[expect]is correctly justified — an#[expect]would fail on macOS where the lint doesn't fire.
Other factors
- Workspace
Cargo.toml:242setslarge_stack_frames = "deny", confirming why this is a hard clippy failure rather than a warning. - No CODEOWNERS entries match either file.
- The PR description's verification (path tests, node parity, clippy repro) is thorough but almost superfluous given zero behavioral surface — nothing here can change what
normalize_string_generic_tzreturns or howinit_runtime_stateexecutes. - No outstanding reviewer comments; only bot activity in the timeline.
Follow-up to #33951, which unbroke `cargo clippy` on the Clippy workflow's runner (`x86_64-unknown-linux-gnu`). The workspace is still not clean on the other hosts, so `bun run rust:clippy` fails for anyone developing on an Apple Silicon Mac, and for the aarch64 Linux target. Measured on `main` (`55ba6e453c`) vs this branch, `cargo clippy --workspace --no-deps --keep-going`: | | macOS arm64 (host) | aarch64-unknown-linux-gnu | x86_64-unknown-linux-gnu | | --- | --- | --- | --- | | `main` | ❌ 2 errors | ❌ 2 errors | ✅ | | this PR | ✅ | ✅ | ✅ | ## `ptr_cast_constness` — aarch64 only `c_char` is `u8` on aarch64 and `i8` on x86_64, so these casts change *only* constness on aarch64 and the lint fires there but not on the runner: - `bun_core::util::dupe_z` — `p as *const c_char` - `bun_alloc::free_sensitive_cstr` — `p as *mut u8`, `p as *mut c_void` Rewritten with `.cast()` / `.cast_const()` / `.cast_mut()`. These are not "smarter" than `as`: in `core` they are literally `#[inline(always)] pub const fn cast_const(self) -> *const T { self as _ }`, so each rewrite is the same single `PtrToPtr` cast with the same address and the same provenance. The `*const` → `*mut` laundering in `free_sensitive_cstr` is pre-existing and unchanged by this PR. The pointer's root is a `default_alloc::malloc` allocation that `dupe_z` already wrote through, so writing through it here was sound before and is sound now — Rust does not track mutability in raw-pointer provenance. ## `derivable_impls` — macOS only `Sendfile`'s `Default` impl is only derivable where the `#[cfg(any(target_os = "linux", target_os = "android"))]` fields are absent. On linux/android the impl carries `socket_fd: Fd::INVALID`, and `Fd` has no `Default` impl at all — `#[derive(Default)]` would not compile there. Suppressed with the reason recorded. `#[allow]` rather than `#[expect]` in both suppression sites, because an expectation would go *unfulfilled* on the platform where the lint doesn't fire, and `warnings = "deny"` would turn that into an error. ## Verification `cargo clippy --workspace --no-deps --keep-going` exits 0 on all three targets above (and `cargo fmt --check` is clean). Built `bun-debug` and exercised the touched crates through the CLI — `path.resolve`/`path.win32.normalize`, `process.env`, `Bun.spawnSync` — plus `bun bd test test/js/node/path/` → 122 pass, 0 fail. Reverting just this commit reproduces both failures on macOS and aarch64, so the changes are load-bearing.
Problem
cargo clippyfails onmain, and therefore on every open pull request that touches a.rsfile. There are two breakages, stacked — the second was hidden becausebun_runtimedepends onbun_paths, so it was never checked whilebun_pathsfailed to compile.1.
bun_paths—clippy::let_and_return#33874 removed the
debug_assertthat used to sit between the binding and the return, leavinglet result = ...;followed byresult.2.
bun_runtime—clippy::large_stack_framesIntroduced by #31216. The frame is
bun_bundler::Transpiler::init's return value: aTranspilercarries aResolverwhoseBSSMapInner<DirInfo, 2048>is ~229 KB, and it is returned by move thenptr::writen straight into(*vm).transpiler. Optimized builds elide the copy; the function runs once per VM init. Only Linux crosses the 128 KBstack-size-thresholdfromclippy.toml, which is why local macOS clippy never flagged it.Why neither was caught
.github/workflows/clippy.ymltriggers onworkflow_call,workflow_dispatch,pull_requestandmerge_group— there is nopush:trigger, so main never lints itself. Becausepull_requestlints the PR merged into main, both breaks surface on contributors' PRs instead, attributed to their commits.Fix
large_stack_framesoninit_runtime_statewith the reason recorded, exactly asfind_context_identifiers::walk_expralready does.#[allow]rather than#[expect]because the lint does not fire on macOS, where an expectation would go unfulfilled. Removing the temporary for real needs an in-placeTranspiler::init_in_place(dst, ..)— a larger change owned by the bundler, and worth doing separately now that every Worker thread runs this init.Verification
maintip before fixing;cargo clippy -p bun_paths --no-depsis clean after (1), andcargo check -p bun_runtime+cargo fmt --checkare clean after (2). CI's ubuntu clippy job is the oracle for (2), since macOS never fires it.bun-debugand drove the surfacenormalize_string_generic_tzactually backs, against a built node v26.3.0 — identical on every case:bun bd test test/js/node/path/→ 122 pass, 2 skip, 0 fail. All 16 vendoredtest-path*.jspass.Notes
A workspace-wide
cargo clippy --workspace --no-deps --keep-goingalso reportsderivable_implsforSendfileinsrc/runtime/server/FileResponseStream.rs, but only on macOS:socket_fd: Fd::INVALIDis a Linux/Android-gated field that is notDefault, so the impl is genuinely not derivable on the Ubuntu runner. Left alone.Adding a
push:trigger toclippy.ymlwould stop this class of breakage from being invisible on main. Happy to do that here or in a follow-up.