Fix sloppy mapped arguments across arrow captures - #12062
Merged
Merged
Conversation
added 4 commits
October 5, 2026 16:29
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configuration
📒 Files selected for processing (14)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Sloppy functions with simple parameters must keep their parameters and arguments indices synchronized. An arrow write through arguments previously left the enclosing parameter stale; the repro produced false 2 50 instead of Node's true 2 1050.
The module-wide boxing collector did not include mapped-arguments parameter cells (
crates/perry-codegen/src/boxed_vars.rs:74). Function prologues boxed the parameters locally, so capture creation forwarded a cell pointer, but arrow bodies projected only the module-wide boxed set (codegen/closure.rs:644) and read the pointer as a value. The shared arguments-elision proof now publishes every materialized mapped cell, while elided read-only arguments keep ordinary slots.Related corrections preserve those prologue cells when scope grouping sees a var redeclaration (
scope_env/pass.rs:72,scope_env/mod.rs:168), derive object-method mapping from actual strictness and parameter form and bind arguments before defaults (lower/expr_object.rs:218,297), make Function constructor bodies independent of enclosing strictness (lower/const_fold_fn.rs:400), and reuse parameter ids for direct/nested function-expression var declarations (lower/expr_function.rs:861,1045). No runtime representation, side table, or registry was introduced.The PR #11955 guard at
lower/unrebound_params.rs:87already invalidates every parameter on any arguments/eval mention, including nested arrows. Production optimizer code is unchanged; the added unit test and sabotage check protect this behavior.Tests: four new Node-compared sloppy gaps, all 21 related gaps, 4 plain-JS copies, and nine new unit tests covering the changed paths and the existing compound-assignment guard. Each fix was removed temporarily; all seven sabotage checks failed and restored checks passed.
Release build of all five required packages: passed. cargo fmt --all -- --check: passed. Full perry-hir tests and codegen doctests passed. Codegen library: 2,030 passed, one ignored. Of 43 codegen integration suites, 42 passed; native_proof_buffer_views had 30 passes and 17 failures, reproduced identically on unmodified main.
scripts/run_lint_gates.sh: 19/126 red on both main and exact head, two CI-only skips. Every failing command matches the baseline; the JSON proof and logs are preserved. GC root-dominance self-tests, poll-reach/macro-position checks, and GC macro-export scanner passed on both arms. No gates or tests were weakened.
Baseline-red commands:
Results: No measured regressions beyond the recorded same-binary A/A spreads.
All builds, tests, and measurements ran on qb6 (AMD EPYC 9354, 64 logical CPUs). Measurements use CPU 11, alternating main/head order. Each timing/RSS result is the median of five runs; each has five interleaved paired same-binary A/A trials. Instructions are the minimum of three
perf stat -e instructions:uruns; three additional same-binary paired trials establish instruction A/A spread. A/A values are full observed ranges divided by medians, shown as main/head. Outputs from every timed and perf run were compared byte-for-byte with Node v26.5.1. JS kernels were erased with Bun v1.4.2build --no-bundle.The complete work directory, including package.json with
perry.compilePackages, was copied. Both tsc build logs showCompile package: typescript; tsc uses argument 1, Zod 200. Prettier uses the copied corpus and bench.ts. The lane copy of tz2.sh reuses the same binaries and independently records seven instruction trials, outputs, full-GC counts, and RSS.Risks: Strict/default/rest/destructured arguments, absent indices at call time, and deleted/recreated indices stay unmapped in the Node comparisons. Materialized mapped cells remain shared through nested arrows, helpers receiving arguments, returned closures, reverse parameter writes, var redeclarations, duplicate parameter names, and compound RHS/key mutations. Tests also cover read-only arguments elision. Baseline lint and native-buffer failures remain open; they are not caused by this patch. The measurement table covers the required workloads; it is not a proof about every possible program.