Skip to content

frontend: same-module enum referenced before its declaration resolves to 0 (silent miscompile) #4510

Description

@proggeramlug

Summary

An enum declared in a module but referenced before its textual declaration
(valid TypeScript — enum bindings are module-scoped) is treated as an unknown
global. Member reads lower to 0 and the compiler emits:

Warning: unknown identifier '<Enum>' — assuming global; member access will
dispatch by name at runtime, bare reads lower to 0

This is a silent miscompile: the binary links but the enum value is wrong.

Minimal repro

function tag(): First { return First.B; }   // used before declaration
enum First { A = "A", B = "B", C = "C" }
console.log("fwd:", tag());
$ perry run fwd_enum.ts
  Warning: unknown identifier 'First' — assuming global; member access will
  dispatch by name at runtime, bare reads lower to 0
fwd: 0

Expected

fwd: B

Notes

  • Moving the enum declaration above its first use makes it work, confirming
    it's a resolution/hoisting-order problem, not an enum-value problem.
  • Found in the wild at scale: zod declares ZodFirstPartyTypeKind near the end
    of zod/src/v3/types.ts and references it earlier throughout the file. Compiling
    zod emits ~90 of these warnings, so zod's internal type-kind dispatch (which
    compares against ZodFirstPartyTypeKind.*) is silently corrupted even once it
    otherwise compiles.
  • May share a root cause with runtime/hir: closure assigning to a forward-declared module-level var loses the write (var hoisting) #4450 (closure write to a forward-declared
    module-level binding is lost) — both look like hoisting/forward-reference
    resolution gaps.

Environment

perry 0.5.1122 · macOS arm64 · native host target.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    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