Skip to content

Fix sloppy mapped arguments across arrow captures - #12062

Merged
proggeramlug merged 4 commits into
mainfrom
fix/sloppy-arguments-from-arrows
Oct 5, 2026
Merged

proggeramlug merged 4 commits into
mainfrom
fix/sloppy-arguments-from-arrows

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

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:87 already 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:

  • [Type-check Windows runtime and stdlib] cargo xwin check -p perry-runtime -p perry-stdlib --target x86_64-pc-windows-msvc
  • [File size limit] ./scripts/check_file_size.sh
  • [Local binding type-proof audit] python3 scripts/local_binding_type_audit.py
  • [GC store-site inventory] python3 scripts/gc_store_site_inventory.py
  • [Address-classification audit] python3 scripts/addr_class_inventory.py
  • [String payload-access inventory] python3 scripts/string_payload_access_inventory.py
  • [SSO string-unboxing inventory] python3 scripts/sso_unbox_inventory.py
  • [Runtime GC-pointer holder custody audit] python3 scripts/gc_runtime_root_holders.py
  • [Native runtime ABI consistency] python3 scripts/runtime_abi_check.py --check-wasm-abi
  • [Raw-handle debt ratchet] python3 scripts/raw_handle_debt.py
  • [Native-handle ledger ratchet] python3 scripts/native_handle_ledger.py --self-test
  • [Unrooted-local shape ratchet] python3 scripts/unrooted_local_shape.py --check
  • [GC matrix liveness gate] ./scripts/gc_repsel_matrix.sh --self-test-fixture-env
  • [Test registration (dark tests)] python3 scripts/check_test_registration.py --self-test
  • [Test registration (dark tests)] python3 scripts/check_test_registration.py
  • [Per-test global sinks] python3 scripts/global_sink_isolation.py
  • [warnings: rustc warnings (host-compatible, all targets)] RUSTFLAGS="-D warnings" cargo check --workspace --all-targets --exclude perry-ui-android --exclude perry-ui-gtk4 --exclude perry-ui-ios --exclude perry-ui-macos --exclude perry-ui-tvos --exclude perry-ui-visionos --exclude perry-ui-watchos --exclude perry-ui-windows --exclude perry-ui-windows-winui
  • [check: Clippy (host-compatible)] cargo clippy --workspace --exclude perry-ui-android --exclude perry-ui-gtk4 --exclude perry-ui-ios --exclude perry-ui-macos --exclude perry-ui-tvos --exclude perry-ui-visionos --exclude perry-ui-watchos --exclude perry-ui-windows --exclude perry-ui-windows-winui
  • [check: Check for API docs drift] git diff --quiet -- docs/src/api/reference.md docs/api/perry.d.ts

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:u runs; 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.2 build --no-bundle.
The complete work directory, including package.json with perry.compilePackages, was copied. Both tsc build logs show Compile 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.

Program Instructions (min 3) CPU ms Wall ms Peak RSS MiB Binary bytes
nbody-ts 13,547,226,739 → 13,547,230,921 (+0.000%); A/A 0.000/0.000% 806.604 → 797.445 (-1.136%); A/A 23.972/22.138% 806.923 → 797.827 (-1.127%); A/A 23.969/22.126% 32.090 → 32.090 (+0.000%); A/A 0.000/0.000% 14032784 → 14032784 (+0.000%)
nbody-js 53,032,329,009 → 53,032,332,645 (+0.000%); A/A 0.000/0.000% 2814.397 → 2772.243 (-1.498%); A/A 42.992/6.563% 2814.909 → 2772.645 (-1.501%); A/A 42.985/6.564% 32.090 → 32.090 (+0.000%); A/A 0.000/0.000% 14081168 → 14081168 (+0.000%)
spectral-ts 18,555,145,021 → 18,555,137,191 (-0.000%); A/A 0.001/0.000% 1705.800 → 1707.501 (+0.100%); A/A 6.013/7.346% 1706.214 → 1707.900 (+0.099%); A/A 6.010/7.342% 32.090 → 32.090 (+0.000%); A/A 0.000/0.000% 13823696 → 13823696 (+0.000%)
spectral-js 35,650,978,408 → 35,650,981,963 (+0.000%); A/A 0.000/0.000% 3463.759 → 2893.170 (-16.473%); A/A 47.078/57.211% 3464.907 → 2893.275 (-16.498%); A/A 47.064/57.179% 32.090 → 32.090 (+0.000%); A/A 0.000/0.000% 13819600 → 13819600 (+0.000%)
fannkuch-ts 78,835,164,236 → 78,835,161,635 (-0.000%); A/A 0.000/0.000% 8072.084 → 7228.092 (-10.456%); A/A 35.499/36.466% 8072.765 → 7228.820 (-10.454%); A/A 35.499/36.463% 32.090 → 32.090 (+0.000%); A/A 0.000/0.000% 13827712 → 13827712 (+0.000%)
fannkuch-js 78,835,160,235 → 78,835,162,678 (+0.000%); A/A 0.000/0.000% 8833.276 → 7394.437 (-16.289%); A/A 28.299/33.784% 8834.743 → 7395.116 (-16.295%); A/A 28.115/33.783% 32.090 → 32.090 (+0.000%); A/A 0.000/0.000% 13827712 → 13827712 (+0.000%)
bintrees-ts 34,944,665,320 → 34,944,592,613 (-0.000%); A/A 0.000/0.000% 2504.118 → 2575.017 (+2.831%); A/A 46.538/78.292% 2504.667 → 2636.054 (+5.246%); A/A 46.207/78.287% 201.500 → 200.609 (-0.442%); A/A 0.534/0.245% 13840144 → 13840144 (+0.000%)
bintrees-js 43,362,585,292 → 43,362,593,811 (+0.000%); A/A 0.000/0.000% 2933.510 → 3086.289 (+5.208%); A/A 75.799/63.953% 2934.516 → 3086.776 (+5.189%); A/A 75.113/64.113% 202.027 → 200.828 (-0.594%); A/A 0.459/0.288% 13831952 → 13831952 (+0.000%)
strs-ts 10,111,308,431 → 10,111,306,538 (-0.000%); A/A 0.001/0.000% 1147.356 → 1157.835 (+0.913%); A/A 38.509/28.362% 1147.786 → 1158.386 (+0.923%); A/A 38.463/28.353% 39.902 → 38.848 (-2.643%); A/A 3.527/2.039% 13881104 → 13881104 (+0.000%)
strs-js 28,505,318,963 → 28,505,322,095 (+0.000%); A/A 0.000/0.000% 3424.055 → 3402.307 (-0.635%); A/A 8.432/34.377% 3424.698 → 3402.863 (-0.638%); A/A 8.426/34.370% 39.738 → 38.758 (-2.467%); A/A 3.403/2.117% 13889296 → 13889296 (+0.000%)
hello-ts 1,214,173 → 1,213,993 (-0.015%); A/A 0.237/0.072% 3.591 → 3.849 (+7.185%); A/A 14.063/15.813% 3.859 → 4.012 (+3.953%); A/A 14.357/18.879% 32.090 → 32.090 (+0.000%); A/A 0.000/0.000% 13782656 → 13782656 (+0.000%)
hello-js 1,215,687 → 1,215,133 (-0.046%); A/A 0.197/0.084% 3.720 → 3.757 (+0.995%); A/A 15.825/8.818% 3.883 → 3.925 (+1.090%); A/A 16.257/8.926% 32.090 → 32.090 (+0.000%); A/A 0.000/0.000% 13782656 → 13782656 (+0.000%)
tsc 10,138,911,156 → 10,139,712,767 (+0.008%); A/A 0.037/0.042% 1134.649 → 1308.078 (+15.285%); A/A 83.738/72.271% 1135.119 → 1308.520 (+15.276%); A/A 83.712/72.250% 215.527 → 215.512 (-0.007%); A/A 1.510/1.469% 136682872 → 136682872 (+0.000%)
zod 762,960,852 → 763,073,419 (+0.015%); A/A 0.065/0.050% 127.457 → 131.720 (+3.345%); A/A 8.230/14.679% 127.857 → 132.111 (+3.327%); A/A 8.174/20.644% 161.887 → 161.887 (+0.000%); A/A 0.000/0.000% 17983824 → 17983824 (+0.000%)
prettier 151,438,830,556 → 151,476,529,224 (+0.025%); A/A 0.029/0.036% 15943.922 → 14669.133 (-7.995%); A/A 60.832/72.740% 15945.210 → 14670.245 (-7.996%); A/A 60.865/72.525% 257.387 → 256.715 (-0.261%); A/A 2.564/2.580% 45450192 → 45450192 (+0.000%)

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.

@coderabbitai

coderabbitai Bot commented Oct 5, 2026

Copy link
Copy Markdown

Review in Change Stack →

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
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b2a71f28-f588-4dd1-95ed-7e424132f561
📥 Commits

Reviewing files that changed from the base of the PR and between 8ff0761 and ba8af9a.

📒 Files selected for processing (14)
  • changelog.d/argsarrow-mapped-arguments.md
  • crates/perry-codegen/src/boxed_vars.rs
  • crates/perry-codegen/src/boxed_vars_mapped_tests.rs
  • crates/perry-codegen/src/scope_env/analysis.rs
  • crates/perry-codegen/src/scope_env/mod.rs
  • crates/perry-codegen/src/scope_env/pass.rs
  • crates/perry-hir/src/lower/const_fold_fn.rs
  • crates/perry-hir/src/lower/expr_function.rs
  • crates/perry-hir/src/lower/expr_object.rs
  • crates/perry-hir/src/lower/unrebound_params_tests.rs
  • test-files/test_gap_argsarrow_function_ctor_sloppy.cts
  • test-files/test_gap_argsarrow_mapped_sloppy.cts
  • test-files/test_gap_argsarrow_methods_sloppy.cts
  • test-files/test_gap_argsarrow_redeclared_sloppy.cts
 ______________________________________________________________________________________________________________________________________________________________________________________________________
< Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. - Brian Kernighan >
 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · 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.

@proggeramlug
proggeramlug merged commit 8aadd76 into main Oct 5, 2026
21 of 25 checks passed
@proggeramlug
proggeramlug deleted the fix/sloppy-arguments-from-arrows branch October 5, 2026 19:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant