Skip to content

fix: preserve multi-type type union when schema has subschemas (#954)#2

Merged
ndreno merged 1 commit into
mainfrom
fix/issue-954-type-union-with-subschemas
May 13, 2026
Merged

fix: preserve multi-type type union when schema has subschemas (#954)#2
ndreno merged 1 commit into
mainfrom
fix/issue-954-type-union-with-subschemas

Conversation

@ndreno
Copy link
Copy Markdown

@ndreno ndreno commented May 13, 2026

Summary

  • Fixes oxidecomputer/typify#954: when a schema had type: [a, b, c, ...] together with oneOf / anyOf / allOf / not, an earlier match arm in convert_schema_object wildcarded the instance_type field and dropped the outer type union. The subschema branches were then converted in isolation, producing an enum that silently lost the non-array (or non-subschema) alternatives.
  • Tightens the match pattern to None | Some(Single(_)) so Some(Vec(_)) falls through to the existing merge arm, which folds the outer schema into each subschema branch via try_merge_with_subschemas. Single-type + subschema behaviour is unchanged (rust-collisions fixture still passes).
  • Adds an 8-case fixture (type-array-with-subschemas.json) covering:
    • type:[...] combined with oneOf, anyOf, allOf, and not
    • explicit type: array in every oneOf branch (primitives pruned)
    • partially and fully unsatisfiable oneOf
    • simultaneous oneOf + allOf
    • singleton-type regression guard (rust-collisions pattern)
  • This was previously submitted upstream as oxidecomputer/typify#1000, which was closed un-merged. Opening on the fork so the fix lives on origin/main.

Test plan

  • cargo test — new fixture passes, existing fixtures unchanged
  • cargo clippy --all-targets
  • cargo fmt --all

…decomputer#954)

When a schema object had both `type: [a, b, c, ...]` and one of
`oneOf`/`anyOf`/`allOf`/`not` on the same level, convert_schema_object
matched an earlier arm that wildcarded the `instance_type` field
(flagged by a pre-existing TODO: "we probably shouldn't ignore this").
The subschema branches were then converted in isolation, silently
discarding the outer type union.

For the schema in issue oxidecomputer#954:

    {
      "type": ["string", "number", "boolean", "array"],
      "oneOf": [
        { "items": { "type": "string" } },
        { "items": { "type": "number" } },
        { "items": { "type": "boolean" } }
      ]
    }

typify produced an enum with only three array variants, losing the
string/number/boolean alternatives entirely.

The fix tightens the match pattern to `None | Some(Single(_))`, letting
`Some(Vec(_))` fall through to the existing merge arm which already
folds the outer schema into each subschema branch via
`try_merge_with_subschemas`. Single-type + subschema behaviour is
preserved, so tolerant handling of schemas whose outer type conflicts
with a branch (e.g. the rust-collisions fixture) is unchanged.

Adds a fixture with eight cases covering the affected code path:
  - `type:[...]` combined with oneOf, anyOf, allOf, and not
  - explicit `type: array` in every oneOf branch (primitives pruned)
  - partially and fully unsatisfiable oneOf
  - simultaneous oneOf + allOf
  - singleton-type regression guard (rust-collisions pattern)

No existing workspace fixture exercised `type: [...]` alongside
subschemas on the same object, so this fix had zero pre-existing
regression coverage.
@ndreno ndreno merged commit c2cbcc3 into main May 13, 2026
@ndreno ndreno deleted the fix/issue-954-type-union-with-subschemas branch May 13, 2026 09:02
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.

Panic: Not yet implemented: unhandled not schema Object

1 participant