Skip to content

[BLOCKER] tdbin rejects struct-form union variants — verify fails on the first union in a real schema #61

Description

@MelbourneDeveloper

Problem

tdbin refuses any union whose variant carries named fields. Our production schema fails on the very first union:

$ typediagram verify docs/models/live-ipc.td
   0:0  error   tdbin: variant 'OpenRange' must be bare or a single tuple field in v0

The offending declaration is ordinary typeDiagram DSL that --to rust, --to typescript, --to csharp etc. all accept:

union FindSimilarInput {
  OpenRange {
    path: String
    start_byte: Int
    end_byte: Int
  }
  Snippet {
    snippet: String
    language: String
  }
}

This is not a rare shape. In one schema we have four of them, and they are all load-bearing wire types:

Union Variants with fields
FindSimilarInput OpenRange { path, start_byte, end_byte }, Snippet { snippet, language }
AnalysisState Running { started_at_ms }, Errored { message }
RequestId Number { value }, String { value }
MergeVerdict AiOrHuman { reason }

Because verify aborts at the first one, tdbin currently covers zero percent of our schema. There is no incremental adoption path — not "most types work", but "the file is rejected".

Why this looks like a generator gap, not a format gap

docs/tdbin-wire-format.html already specifies the encoding:

"Records and struct-unions are pointer-encoded as separate objects."

and the evolution rules already talk about payload variants:

"Appending bare or payload variants to unions (if discriminant width unchanged)"

So the wire format contemplates struct-shaped variants. The restriction appears to live in the emitter/verifier, phrased as a v0 limitation.

Ask

Support struct-form union variants in encode / decode / verify, encoded per the existing struct-union pointer rules: discriminant in the data section, variant payload as a pointer to a struct laid out by the normal [TDBIN-REC-ALLOC] rules.

If that genuinely cannot land in v0, then at minimum:

  1. Make the error message say what the workaround is, and
  2. Do not abort the whole file — report every unsupported declaration in one pass so a consumer can see the total scope of the problem instead of fixing one and re-running.

Rewriting each variant into a named side record is not an acceptable workaround for us: the .td file is the single source of truth for the JSON wire shape and the Rust/TS types, and flattening the unions changes the JSON representation that shipped clients already depend on.

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

    CRITICALCritical severity — fix immediately

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions