Skip to content

test: gc-dep-corpus does not link (zod export * re-exports) — blocks #7803 #7964

Closed

Description

@proggeramlug

Summary

test-files/gc-dep-corpus/main.ts does not link, on a pristine origin/main build:

Undefined symbols: _perry_fn_node_modules_zod_src_v4_core_index_ts__NEVER
                   _perry_fn_node_modules_zod_src_v4_core_index_ts__brand
                   ...

The failing symbols are the export * re-export set in the currently pinned zod@4.3.5.

Why this matters beyond one corpus

#7803's reproducer is not runnable as written. That issue asks for the zod dep-corpus under PERRY_GC_SCHEDULE_RATE=1 with the quarantine off; the corpus cannot be built at all, so the issue cannot be actioned or refuted until this is fixed. Verified identical on a pristine origin/main worktree — this is not branch-attributable (found while working #7949, gc-handoff/ROOTVEC-NOTES.md).

A dependency corpus that no longer links is also a gate that cannot fail, in the sense CLAUDE.md means: whatever it was meant to cover, it has been covering nothing since the break.

Suggested disposition

Either fix the export * re-export handling for this shape, or regenerate/re-pin the corpus — but say which, because "regenerate the corpus" would silently discard whatever compiler bug the current pin is exercising. If the pin is regenerated, check first whether the symbols are unresolved because of a genuine export * gap; that would be a compiler issue worth its own ticket rather than a corpus refresh.

Related

Activity

  1. self-assigned this
    on Aug 12, 2026
  2. added a commit that references this issue on Aug 12, 2026
  3. proggeramlug commented on Aug 12, 2026

    @proggeramlug
    ContributorAuthor

    Verdict: genuine compiler gap, not a stale pin. Do not regenerate the corpus.

    Reproduced on a build of origin/main (a769faf) with PERRY_NO_AUTO_OPTIMIZE=1 and PERRY_RUNTIME_DIR pinned: test-files/gc-dep-corpus/main.ts fails to link with 45 distinct undefined _perry_fn_node_modules_zod_… symbols.

    1. Every failing symbol names the BARREL as the definer

    _perry_fn_node_modules_zod_src_v4_core_index_ts__NEVER
    _perry_fn_node_modules_zod_src_v4_core_index_ts___brand
    _perry_fn_node_modules_zod_src_v4_core_index_ts__globalRegistry
    _perry_fn_node_modules_zod_src_v4_core_index_ts__clone
    _perry_fn_node_modules_zod_src_v4_core_index_ts__prettifyError
    _perry_fn_node_modules_zod_src_v4_core_index_ts___gt        (… and 39 more)
    

    The mangled module is core/index.ts. That file is sixteen lines of export * from … / export * as ns from … and defines nothing; NEVER is core/core.ts:13, globalRegistry is core/registries.ts:105, clone is core/util.ts:485, _gt is core/api.ts:875. Perry emits a reference to a definition that, by construction, cannot exist in the barrel.

    2. The consumer shape is a named re-export from an export * barrel

    src/v4/classic/external.ts:14-31:

    export { globalRegistry, registry, config, $output, $input, $brand, clone,
             regexes, treeifyError, prettifyError, … } from "../core/index.js";

    Every one of those names reaches core/index.ts only via export * from "./core.js" | "./api.js" | "./registries.js" | "./errors.js". So the failing construct is export { X } from "<barrel>" where the barrel obtained X through export * — the forwarding definition is never emitted.

    3. It is not a type-only-export leak

    The failing set mixes const exports (NEVER, globalRegistry, $brand) with function exports (config, clone, prettifyError, _gt, _minLength, …). "An erased type export still got a symbol" does not explain it.

    4. The pin has not drifted

    package.json asks for zod@^4.3.5; node_modules/zod/package.json is 4.3.5 — exactly the version this issue names. Nothing in the corpus pins a commit that could have moved underneath it. Regenerating would discard a real defect and buy nothing.

    Reproducer status

    Two minimal fixtures I built both link cleanly, so the gap needs more of zod's shape than one hop:

    • leaf.ts (export const + export function) → barrel.ts (export * from "./leaf.js") → top.ts (import * as B) — links.
    • … plus bridge.ts (export { NEVER, greet } from "./barrel.js") → top2.ts — also links.

    Remaining candidates for the trigger: the barrel's multi-source export * set, its export * as ns from entries, and the core/index.ts ↔ core/api.ts cycle (api.ts is re-exported by the barrel and also imports from it).

    Note on ownership

    /Users/amlug/projects/perry/wt-codex-7964 is another agent's worktree on branch fix/7964-zod-star-reexports, already carrying uncommitted edits to crates/perry-hir/src/lower/module_decl.rs, crates/perry-hir/src/dynamic_import.rs and crates/perry-codegen/src/codegen/helpers.rs, plus fixtures test-files/test_gap_export_star_variable_reexport.ts and test-files/_helpers/issue_7964_{leaf,barrel,bridge,top}.ts — the same four-file shape I arrived at independently. I stopped at the verdict rather than shipping a second implementation of the same fix.

    Consequence for #7803

    Still blocked: the corpus does not link, so #7803's reproducer cannot be run. PR #7978 (the Object.defineProperty rooting fix for #7963) does not change that — it is runtime-side, and this failure is in module lowering/codegen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions