Skip to content

refactor(codegen): split codegen/artifacts.rs under the file-size cap - #11093

Closed
proggeramlug wants to merge 1 commit into
mainfrom
fix/artifacts-size-cap
Closed

proggeramlug wants to merge 1 commit into
mainfrom
fix/artifacts-size-cap

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

crates/perry-codegen/src/codegen/artifacts.rs sat at 1999 lines against
the hard 2000-line cap enforced by scripts/check_file_size.sh (a required
lint step). One line of headroom means any PR that adds even two lines to it
is blocked outright — #11087 concretely. This splits it so it stops being a
tripwire.

Redone from scratch on top of 7f4417b5a1 (merge train 259). Train 259's
b8c2457e4e edits artifacts.rs inside the very range this PR moves, so the
earlier revision conflicted. Rather than hand-merge a move against an edit —
which is how a hunk silently goes missing — the split was re-cut at the same
progress.checkpoint(...) phase boundaries against the new file, and both
blocks re-verified byte-identical to their new-main originals.

Before / after

file before after
crates/perry-codegen/src/codegen/artifacts.rs 1999 1044
crates/perry-codegen/src/codegen/class_artifacts.rs 572 (new)
crates/perry-codegen/src/codegen/export_value_wrappers.rs 530 (new)

What moved

artifacts.rs was a single 1958-line emit_module_artifacts function, so the
split is by phase, cut at the existing progress.checkpoint(...) boundaries.

Both siblings follow the convention already in codegen/
(ordinary_method_artifacts.rs, indexed_method_artifacts.rs): a
pub(super) XxxCtx<'a> struct of borrowed inputs plus a pub(super) fn that
destructures it, declared as a plain mod in codegen/mod.rs and imported
with explicit named use (no globs).

Purity

Both moved blocks are byte-identical to the originals — verified by diffing
the extracted line ranges out of git show HEAD:…/artifacts.rs against the
corresponding ranges of the two new files (G1 IDENTICAL, G2 IDENTICAL).
Comments, ?/with_context chains and the c.cross_module partial-move read
all came along verbatim; the new functions take their ctx as c precisely so
that read stays unchanged.

Two edits are not moves:

  • #[derive(Clone, Copy)] on OptsView in artifact_context.rs, so the class
    phase can take the same by-value view without the artifact tail losing its
    own. Every field of OptsView was already a shared borrow or a scalar, so
    this adds no semantics — same "minimum glue for the split" category as the
    visibility bumps in refactor(runtime): split value/to_string.rs under the file-size cap #11088.
  • scripts/shape_descriptor_census_baseline.json repoints one callsite key
    from artifacts.rs to class_artifacts.rs. That census pins callsites by
    file path
    , so a pure move reads to it as one site removed and one added.
    The multiset is otherwise untouched, and its summary still reports
    codegen_object_header_size_sites: 43.

No renames, no version bump.

Verification

Each cargo command was re-run after touching the moved files, so the
Checking … line proves the crate was actually re-analysed rather than served
from cache.

$ bash scripts/check_file_size.sh
OK: no Rust source files exceed 2000 lines.

$ cargo fmt --all -- --check
(no output, exit 0)

$ cargo check -p perry --bins
    Checking perry-codegen v0.5.1642 (/Users/amlug/wt-artifacts-split/crates/perry-codegen)
    Checking perry v0.5.1642 (/Users/amlug/wt-artifacts-split/crates/perry)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 8.97s

$ python3 scripts/shape_descriptor_census.py
{
  "codegen_object_header_size_sites": 43,
  "raw_member_files": 12,
  "raw_member_sites": {
    "keys_array": 35
  }
}

$ python3 scripts/addr_class_inventory.py
Address-classification audit passed (1623 files scanned, 317 allowlisted, 505 known sites held by the ratchet).

$ python3 scripts/raw_handle_debt.py
raw-handle debt sites: 901 (baseline 901)
per-module: 104 module(s) within ceilings; every other runtime module is locked at zero

$ python3 scripts/raw_handle_debt.py --no-raise-vs origin/main
recorded debt vs. origin/main: baseline 901 -> 901, 104 -> 104 module ceiling(s), none raised

$ python3 scripts/gc_runtime_root_holders.py
gc_runtime_root_holders: OK — 1513 holder declarations scanned (1283 identity-ratcheted), 664 reached by a registered scanner, 433 classified in the inventory, 409 pinned on the frontier ratchet (149 registered scanners).

cargo check -p perry --bins is the warnings gate's own command and a
different feature set from -p perry-codegen; it is what caught #11088's bug
(an import left unconditional while its sole remaining caller sat behind a
#[cfg(feature = ...)]). Nothing of that shape came up here — neither
extracted block has a cfg-gated call site.

Path-keyed gates

addr_class_ratchet_baseline.txt, addr_class_allowlist.txt,
raw_handle_debt_files.txt and gc_runtime_root_holders.json hold no
codegen/artifacts.rs entry, so there was no ceiling to relocate and no
# moved-from: declaration to write — which is why the merge-base invocation
of raw_handle_debt.py reports none raised rather than a declared
relocation. Only the census baseline was path-keyed to this file.

Beyond the five script baselines, the crate also carries source-level
path allowlists that a file split can disturb: pshape_symbol_reachability
and spec_abi_symbol_reachability each hold a fixed-size [&str; N] array of
src-relative paths. Neither is tripped here (neither moved block contains
$pshape or $spec_), and the whole class is covered by:

$ cargo test -p perry-codegen --lib
test result: ok. 1674 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 3.36s

Finally, all 35 static (no-build) lint gates from test.yml's lint job
were run against this tree and pass, including workspace_architecture.py,
check_gc_header_constants.py, gc_store_site_inventory.py,
string_payload_access_inventory.py, check_test_registration.py,
unrooted_local_shape.py --check, and both merge-base ratchets
(unrooted_local_shape.py / global_sink_isolation.py --asserted-no-raise-vs).

Summary by CodeRabbit

  • Refactor
    • Class artifact and exported-value wrapper generation are now handled separately. No changes to end-user functionality or application behavior are reported.

@coderabbitai

coderabbitai Bot commented Sep 23, 2026

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 135bf1d1-65bd-4cb9-8c95-7f6a7d605294

📥 Commits

Reviewing files that changed from the base of the PR and between bc019bb and fcf8c33.

📒 Files selected for processing (4)
  • changelog.d/11093-artifacts-size-cap.md
  • crates/perry-codegen/src/codegen/artifacts.rs
  • crates/perry-codegen/src/codegen/export_value_wrappers.rs
  • scripts/shape_descriptor_census_baseline.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • changelog.d/11093-artifacts-size-cap.md

Included review availability: Your plan provides up to 8 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

Codegen now delegates class artifact generation and exported value wrapper generation to separate modules. The class helper emits methods, constructors, accessors, and static members. The wrapper helper emits import getters, function wrappers, and export aliases. OptsView now derives Clone and Copy.

Changes

Artifact emission

Layer / File(s) Summary
Class artifact compilation
crates/perry-codegen/src/codegen/class_artifacts.rs, crates/perry-codegen/src/codegen/artifact_context.rs
A new helper compiles typed and indexed method clones, ordinary methods, computed members, accessors, constructors, and static members. OptsView derives Clone and Copy.
Export value wrappers
crates/perry-codegen/src/codegen/export_value_wrappers.rs
A new helper emits Node-core import getters, function wrappers, and aliases for exported names.
Artifact helper integration
crates/perry-codegen/src/codegen/artifacts.rs, crates/perry-codegen/src/codegen/mod.rs, changelog.d/11093-artifacts-size-cap.md, scripts/shape_descriptor_census_baseline.json
emit_module_artifacts calls both helpers, and the codegen module registers them. The changelog records the extraction and reported checks. The census baseline points to the moved callsite.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Refactor

Merge Risk: ⚪ Minimal · up to fcf8c

This change reorganizes code generation into smaller modules without changing what gets generated. Class methods, constructors, accessors, and exported function wrappers are emitted in the same order with the same logic as before. No merge-blocking risk was found.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 5 files. (2 skipped: 2 …
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.
Title check ✅ Passed The title clearly identifies the main change: splitting codegen/artifacts.rs to satisfy the file-size cap.
Description check ✅ Passed The description gives a detailed summary, lists the moved modules and non-move edits, explains the rationale, and provides extensive verification results. It does not use every template heading or che…
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

`crates/perry-codegen/src/codegen/artifacts.rs` sat at 1999 lines against the
hard 2000-line cap enforced by `scripts/check_file_size.sh` (a required `lint`
step), so any PR that added even two lines to it was blocked outright —
#11087 concretely.

Pure move, no behavior change:

- `class_artifacts.rs` (new, 572 lines) — the per-class walk: instance methods
  and their typed/indexed/proven-`this` clones, computed members, accessors,
  the standalone constructor, and statics.
- `export_value_wrappers.rs` (new, 530 lines) — the exported function-value
  surface: live getters for re-exported native named imports, the
  `__perry_wrap_*` closure-ABI wrappers, and the cross-module raw/renamed name
  aliases.
- `artifacts.rs` 1999 -> 1044 lines.

Both moved blocks are byte-identical to the originals (verified by diffing the
extracted line ranges against `git show HEAD:`). Both siblings follow the
existing `codegen/` convention (`ordinary_method_artifacts.rs`,
`indexed_method_artifacts.rs`): a `pub(super) XxxCtx<'a>` struct of borrowed
inputs plus a `pub(super) fn` that destructures it, declared as a plain `mod`
in `codegen/mod.rs` and imported with explicit named `use`.

Two edits are not moves:

- `#[derive(Clone, Copy)]` on `OptsView` in `artifact_context.rs`, so the class
  phase can take the same by-value view without the artifact tail losing its
  own; every field was already a shared borrow or a scalar.
- `scripts/shape_descriptor_census_baseline.json` repoints its
  `object_header_size_bytes(target_triple)` callsite from `artifacts.rs` to
  `class_artifacts.rs`. That census pins callsites by file path, so a pure move
  reads to it as one site removed and one added.
@proggeramlug

Copy link
Copy Markdown
Contributor Author

Landed on main in merge train 265 (#11108), released as v0.5.1648 at 9d26936298.

Cherry-picked from this PR's head fcf8c33e59 and validated as one tree with 15 other PRs — CI 22/22 green, all 6 gap-suite shards. A train rebase gives the commits new SHAs, so GitHub cannot auto-close the source PR; closing by hand.

Nothing needed from you. Thanks.

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