Skip to content

fix(analysis): requiredness branches may restate type: object - #91

Merged
lightsofapollo merged 2 commits into
gpu-cli:mainfrom
iamralch:fix/allof-constraint-only-unions
Oct 2, 2026
Merged

lightsofapollo merged 2 commits into
gpu-cli:mainfrom
iamralch:fix/allof-constraint-only-unions

Conversation

@iamralch

@iamralch iamralch commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Fixes #88.

What was wrong

A union whose branches only list required properties constrains the object; it isn't a variant of it. union_only_constrains_requiredness already treats it that way, but only when each branch has nothing but required, not, nested unions and annotations. A branch that also says type: object was read as an empty object variant:

Email:
  type: object
  required: [from]
  properties: { from: ..., to: ..., cc: ..., text: ..., html: ... }
  allOf:
    - anyOf:
        - { type: object, required: [to] }
        - { type: object, required: [cc] }
    - anyOf:
        - { type: object, required: [text] }
        - { type: object, required: [html] }

With two of them in an allOf, generation failed:

Error: Invalid schema: allOf object `Email` intersects multiple union members (`EmailAllOfVariant1` and `EmailAllOfVariant2`), which cannot be represented by one flattened variant

and one beside a real union competed with it for the variant.

The change

schema_only_constrains_requiredness also accepts type: "object" in a branch, and nothing else for type. Only an object has required properties, so it says nothing the requiredness doesn't.

Tests

In tests/recoverable_typing_test.rs, beside the existing requiredness case:

  • requiredness_branches_that_restate_type_object_are_still_only_requiredness: the schema above, Cloudflare's Email Sending builder, is a struct of its properties.
  • a_requiredness_union_beside_a_real_union_leaves_that_union_the_variant: Cloudflare's Magic WAN app config, a oneOf of account or managed app beside an anyOf of required: [breakout] or required: [priority], keeps the oneOf as its variant.

Both fail before this change. cargo test --all-features: 720 passed, none failed.

The corpus doesn't move: scripts/gen-diff.sh upstream/main reports every spec identical, since no pinned spec has such a branch. The pinned cloudflare spec predates both of these schemas. Against the current cloudflare/api-schemas, both now generate, without the overlay we used to work around them.

#88 lists a third Cloudflare case, the Workers Observability filters: an allOf of a $ref to a union and an inline copy of the same union. That isn't requiredness, and this doesn't change it.

This and #90 both add a Fixed entry under [Unreleased] in CHANGELOG.md, so whichever merges second needs that resolved. I'll rebase.

A union whose branches only list required properties constrains the
object; it isn't a variant of it. A branch that also says `type: object`
was read as an empty object variant, though only an object has required
properties, so it says nothing the requiredness doesn't. An `allOf` of
two such unions then failed as intersecting multiple union members, and
one beside a real union competed with it for the variant.

The corpus doesn't change: no pinned spec has such a branch.

Fixes gpu-cli#88
@vercel

vercel Bot commented Oct 2, 2026

Copy link
Copy Markdown

@iamralch is attempting to deploy a commit to the lbl-rd Team on Vercel.

A member of the Team first needs to authorize it.

@lightsofapollo
lightsofapollo merged commit c7a570c into gpu-cli:main Oct 2, 2026
12 of 13 checks passed
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.

allOf of constraint-only anyOfs is rejected when the branches say type: object

2 participants