Skip to content

feat(hir): supply native parsers for static Zod schemas - #9040

Draft
proggeramlug wants to merge 3 commits into
mainfrom
feat/zod-compile-aot
Draft

feat(hir): supply native parsers for static Zod schemas#9040
proggeramlug wants to merge 3 commits into
mainfrom
feat/zod-compile-aot

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Summary

AOT-compiles a conservative static subset of Zod z.compile() while keeping Zod?not Perry?as the owner of schema semantics.

Perry recognizes a closed z.object({...}), emits only a native parser, and passes that parser to the proposed Zod compileFromParser() API. Zod's own TypeScript remains responsible for cloning, async/backward/skip-check bypasses, recursion guards, public parse methods, validation, and authoritative runtime fallback.

This remains a draft because it depends on the upstream Zod integration API proposed in colinhacks/zod#6498.

Architecture

static schema source
       |
       v
Perry schema IR -> native parser (value | z.INVALID)
                              |
                              v
                 z.compileFromParser(schema, parser)
                              |
                              v
         Zod-owned clone / wrapper / fallback / public API

There is no Perry reimplementation of Zod's compiled wrapper contract. Unsupported schemas and Zod versions without compileFromParser() retain the ordinary z.compile(schema, options) call.

Changes

  • Extract compiler-only IR from immutable static z.object({...}) declarations imported from zod / zod/v4.
  • Lower string, finite-number, boolean, and number int / literal min / literal max checks to native Perry HIR.
  • Return Zod's exported INVALID sentinel from the native parser and install it through Zod's compileFromParser().
  • Decline mutable schemas, shadowed Zod namespace bindings, duplicate keys, __proto__, unsupported schemas, and dynamic options rather than partially specializing them.
  • Let compilePackages enter a TypeScript source tree even when the package's built exports target is absent. This makes the temporary source-only Zod pin reproducible.
  • Pin the POC to the public source-only Zod commit ee27e77ad86238199cfa0c262cfa2c7dfc125e49 and opt Zod into perry.compilePackages.
  • Add HIR/resolver regressions, a conformance fixture, a real-Zod probe, and a changelog fragment.

Current supported subset

  • import * as z from 'zod' or 'zod/v4'
  • immutable const schema bindings
  • z.object() with static, unique, non-computed fields
  • z.string(), z.number(), and z.boolean()
  • z.number().int(), .min(<number literal>), and .max(<number literal>)
  • z.compile(schema) and static { strict: <boolean> }

Everything else remains on Zod's normal runtime path.

Upstream dependency / landing decision

The Zod-side API implementation is available at:

Before this Perry PR leaves draft, we should agree that:

  1. Zod accepts an API equivalent to compileFromParser(schema, parser, { validator? }) plus an exported failure sentinel.
  2. The final Perry dependency uses the first official Zod release containing that API; the fork commit is only for this draft POC.
  3. Perry continues to fail closed: only exact statically proven shapes specialize, and all other calls remain Zod-owned.

Test plan

  • npm ci --ignore-scripts --dry-run
  • cargo test -p perry-hir --lib (360 passed, 1 pre-existing ignored before rebase)
  • cargo test -p perry-hir zod_aot --lib after rebasing onto current main (5 passed)
  • cargo test -p perry --bin perry compile_package_resolves_source_without_built_exports_target
  • cargo build --profile perry-dev -p perry
  • End-to-end compile after rebase: 95 Zod source modules native, 0 JavaScript
  • Auto-optimized runtime features: async-runtime,web-fetch (no dyn-eval)
  • 27.7 MB native executable; valid input avoids fallback, unknown keys strip, invalid input delegates to Zod
  • Wrapper __originalRun and bag.fallbackRun identities prove installation is Zod-owned
  • Zod targeted compile tests: 462 passed across all configured projects
  • Zod full compile suite: 2645 passed; 2 unrelated existing Windows esbuild path-escaping failures
  • Zod package build (zshy) passes
  • Full Perry workspace CI

Verified output

true
true
true
true
true
true
true
false
true
score:invalid_type

The assertions cover schema cloning, replacement of _zod.run, Zod ownership of the wrapper and fallback, native valid parsing without fallback, unknown-key stripping, invalid fallback, and the final Zod issue.

Checklist

  • No workspace version bump or direct CHANGELOG.md edit
  • Commits follow the repository prefix convention
  • Read CONTRIBUTING.md and agree to the Code of Conduct

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

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 changed the title feat(hir): lower static Zod schemas to native validators feat(hir): supply native parsers for static Zod schemas Aug 29, 2026
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