Skip to content

fix(compilers/openapi): elect an alias tag by byte order - #455

Open
fuad-daoud wants to merge 1 commit into
mainfrom
fix/discriminator-alias-mapping
Open

fix(compilers/openapi): elect an alias tag by byte order#455
fuad-daoud wants to merge 1 commit into
mainfrom
fix/discriminator-alias-mapping

Conversation

@fuad-daoud

Copy link
Copy Markdown
Collaborator

Summary

A discriminator mapping may spell several keys for one subtype — an alias tag — and Model.DiscriminatorValue holds one. The subtype took whichever key was written first, so two documents differing only in the order of two mapping lines lowered differently, with no diagnostic in either (#410). A mapping is unordered, so its key order is not a property of the document, and this is the class of order-dependence the order-invariance oracle exists to reject — it just never met the shape, because no committed spec declared two keys for one target.

The subtype now takes the smallest key in byte order, whichever was written first. That is an election rule rather than a heuristic: which key the author "meant" is not knowable, either is valid on the wire, and the base's Discriminator.Mapping keeps every key, so the routing table an emitter needs for deserialization is intact. The election narrows what the subtype's field shows and loses nothing, and it is reported at the subtype as an info openapi/degraded-construct naming every key, so a reader knows the tag set is wider than the field. ir-design.md's OpenAPI lowering row records the rule beside the other election rules (const/enum/allOf, oneOf over anyOf).

mappingTagsFor is the only site that picks from a mapping; discriminatorMapping keeps every key and discriminatorDefault is single-valued by construction, so there is no second site of the mechanism.

Test plan

  • TestAllOf_DiscriminatorAliasTagIsOrderInvariant (new, internal/schema): the issue's document in both key orders, the larger-first order included — the one a first-key-wins reading gets wrong. Red before the fix on that order, green after.
  • New conformance fixture discriminator-alias-mapping.yaml, witnessing tagged-unions, declared larger-first for the same reason. Planting first-key-wins back reddens all three guards: the unit test, the golden, and morphic-harness, which now reports order-dependent type registry on the fixture — so the oracle meets this shape from now on.
  • make gate passes: lint 0 issues, coverage at 100%, fuzz, bench-smoke.

Closes #410

🤖 Generated with Claude Code

https://claude.ai/code/session_01TJZJ8HaugGZTjzVueafLAT

A discriminator mapping may spell several keys for one subtype — an
alias tag — and Model.DiscriminatorValue holds one. The subtype took
whichever key was written first, so two documents differing only in
the order of two mapping lines lowered differently, with no diagnostic
in either (GitHub #410). A mapping is unordered, so its key order is not
a property of the document.

The subtype now takes the smallest key in byte order, whichever was
written first. The base's Discriminator.Mapping keeps every key, so the
election narrows what the subtype's field shows and loses nothing, and
it is reported at the subtype as an info degraded-construct so a reader
knows the tag set is wider than the field. ir-design's OpenAPI lowering
row records the rule.

A conformance fixture declares the keys larger-first — the order a
first-key-wins reading gets wrong — so the order-invariance oracle meets
the shape from now on, which no committed spec had let it do.

Closes #410

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TJZJ8HaugGZTjzVueafLAT
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.

openapi: a subtype named by two mapping keys takes whichever is declared first

1 participant