Skip to content

fix(core/emitter): widen string-literal enum tag to u16 for 257+ members - #200

Open
zuohuadong wants to merge 1 commit into
vercel-labs:mainfrom
zuohuadong:fix/emitter-enum-tag-width
Open

fix(core/emitter): widen string-literal enum tag to u16 for 257+ members#200
zuohuadong wants to merge 1 commit into
vercel-labs:mainfrom
zuohuadong:fix/emitter-enum-tag-width

Conversation

@zuohuadong

Copy link
Copy Markdown

Summary

R5 emits every string-literal union as enum(u8). Once a union has 257 or more members, the zero-based ordinals exceed the u8 range and Zig rejects the generated declaration (enum(u8) cannot hold member value 256). Apps with large generated unions currently need a local overlay to build.

This change uses enum(u16) only when members.length > 256; unions with 256 members still occupy ordinals 0..255 and stay enum(u8). Wire order, payload layout, and the one-line/multi-line formatting paths are unchanged.

Why this is general (not app-specific)

The u8 ceiling is a property of Zig's enum(u8) representation, not of any app's domain. Any Native SDK app whose transpiled Msg/catalog union crosses 257 members hits this today and must carry a local emitter patch. Keeping it local means every SDK upgrade re-baselines the overlay; landing it upstream removes that surface for everyone.

Behavior

members before after
3 enum(u8) enum(u8) (unchanged)
256 enum(u8) (overflows at runtime once a member maps to 255 is fine, but a 257th member cannot be represented) enum(u8) (unchanged; 256 members occupy 0..255)
257+ enum(u8) (fails to compile) enum(u16)

Test coverage

  • Existing R5 string-literal union becomes a wire-stable enum still asserts enum(u8) for 3 members.
  • New R5 string-literal union with 257+ members emits enum(u16) asserts enum(u16), m0 = 0,, m256 = 256,.
  • New R5 string-literal union with exactly 256 members stays enum(u8) guards the boundary.

`packages/core` test suite: 152/152 pass with the change.

Compatibility

No wire/protocol change: the on-the-wire tag is the declaration ordinal, and consumers that compare by tag name (.all, .done, switch scrutinee) are unaffected. A u16 tag is a strict superset of u8 for apps that currently fit in u8.

R5 emitted every string-literal union as enum(u8), which overflows the
u8 ordinal range once a union has 257 or more members (Zig rejects
member values >= 256 under enum(u8)). Apps with large generated unions
currently need a local overlay to build.

Use enum(u16) only when members.length > 256; 256 members still occupy
ordinals 0..255 and stay enum(u8). Wire order, payload layout and the
one-line/multi-line formatting paths are unchanged.
@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown

@zas4exd is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

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.

2 participants