Skip to content

fix(hir): run static class blocks at declaration source position (#2278)#2285

Merged
proggeramlug merged 1 commit into
mainfrom
worktree-fix-2278-static-block-init
May 28, 2026
Merged

fix(hir): run static class blocks at declaration source position (#2278)#2285
proggeramlug merged 1 commit into
mainfrom
worktree-fix-2278-static-block-init

Conversation

@proggeramlug
Copy link
Copy Markdown
Contributor

@proggeramlug proggeramlug commented May 28, 2026

Summary

Update (post-rebase): the equivalent HIR + codegen fix for #2278 landed on main via a parallel PR while this branch was in CI. Rebased onto current main, kept the parts that are still uniquely additive:

  • test-parity/node-suite/object/class-static-block.ts — a dedicated parity test with five variations (basic boolean, field+block override, multi-assignment in a single block, two blocks on one class, self-reference) byte-identical against node --experimental-strip-types. The existing fix only had test_gap_class_advanced.ts covering one shape.
  • Issue-ref polish in the comments above init_static_fields_late and the new init_calls_static_block helper so the rationale for the dedup loop links back to Static class block assigning true to a static boolean field reads back 0 (init missed) #2278 directly.

The original commit body (HIR emission at class-decl source position + late-pass dedup) is now redundant with main; the gap test is the residual carrier of the fix's intent for the test suite.

Test plan

  • cargo fmt --all -- --check clean.
  • cargo test --release -p perry-codegen -p perry-hir green.
  • test-parity/node-suite/object/class-static-block.ts byte-identical against Node.
  • test-files/test_gap_class_advanced.ts still byte-identical (already removed from known_failures.json upstream).

Refs #2278.

`static { ... }` blocks now emit a synthetic
`Class.__perry_static_init_N()` call at the class declaration's
source position in `lower/stmt.rs::Decl::Class`, mirroring how
static field initializers are already emitted there. Pre-fix the
only emitter was `init_static_fields_late`, which runs AFTER every
module-level stmt — so a `console.log(C.staticField)` on the line
after a class declaration read the field's zero default instead of
the value the block had assigned.

The late pass keeps calling static blocks for any class that
*didn't* get an inline call emitted (inner classes hoisted into
`hir.classes` from a function body still hit this fallback). A new
`collect_classes_with_inline_static_block_calls` helper scans
`hir.init` for the synthetic calls and dedupes them out of the late
pass so we don't double-execute.

Closes #2278; clears the residual gap entry in `test_gap_class_advanced.ts`.
@proggeramlug proggeramlug force-pushed the worktree-fix-2278-static-block-init branch from ada35c3 to f5aac4d Compare May 28, 2026 19:14
@proggeramlug proggeramlug merged commit e6ada80 into main May 28, 2026
20 of 22 checks passed
@proggeramlug proggeramlug deleted the worktree-fix-2278-static-block-init branch May 28, 2026 19:33
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