Repository navigation
fix(generator): leave union-declared required names to the variant - #103
Merged
lightsofapollo merged 2 commits intoOct 12, 2026
Merged
Conversation
An object that pairs shared fields with a union, through allOf or as sibling properties and anyOf/oneOf, synthesized a required serde_json::Value field for every required name absent from the shared properties, even when the union's branches declare it. Cloudflare's dns-records_dns-record-response lists `data` as required though only CAA, SRV and similar record types carry it, so A and MX records failed to deserialize with "missing field `data`", and name, content and ttl were untyped. Required names declared by any branch reachable through the union are now left to the variant, which types them and keeps each branch's own optionality. Names declared nowhere keep the existing placeholder. The corpus change is confined to Cloudflare's DNS record response types.
|
@gilesw is attempting to deploy a commit to the lbl-rd Team on Vercel. A member of the Team first needs to authorize it. |
9 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When an object pairs shared fields with a union, the generator emits a base struct plus a flattened
variant. Arequiredname that the shared fields don't declare got a synthesized requiredserde_json::Valuefield on the base struct, even when the union's branches declare that name with a real type.Cloudflare's
dns-records_dns-record-responsehits this. Its outerrequiredlist isname, type, content, data, proxied, ttl, settings, comment, tags. All of those are declared only inside the per-record-type branches, anddataexists only on CAA, SRV, HTTPS and similar records. The result:missing field `data`name,content,ttl,typeand the other fields are typedserde_json::Valueon the base struct, even though the branch structs already carry them typed (for examplecontent: Option<std::net::Ipv4Addr>onARecord)The bug occurs in both forms the schema takes: the current spec uses
allOf: [anyOf: [...], {properties}], and the corpus-pinned spec putspropertiesandanyOfside by side.This PR leaves a required name to the variant when any branch reachable through the union declares it. The branch types the field and keeps its own optionality. A required name that no shared member or branch declares still gets the existing placeholder.
Generated compatibility
DnsRecordsDnsRecordResponseand four DNS operationResponse4xxResulttypes that embed it.types.rsshrinks by 210 lines. No other spec changes.dataon an A record, now decode.Validation
tests/allof_object_union_preservation_test.rsin both forms:RecordResponse(allOf) andSiblingRecordResponse(siblingproperties+anyOf). It checks that the base struct no longer owns the branch-declared names, and round-trips A, MX and CAA records through a compiled scratch crate. Both tests fail without the change withmissing field `data`.cargo fmt --checkcargo clippy --all-features -- -D warningscargo nextest run --all-features --no-fail-fast: 726 run, all pass. In an earlier run,required_undeclared_members_round_trip_untyped_and_typed_valuesfailed while other cargo builds were running on the machine. It passed when rerun alone and in the full rerun.cargo test --doc --all-featuresandcargo doc --no-deps --all-featureswith-Dwarningsscripts/spec-compile.sh anthropic openai: both PASS + ROUNDTRIPtests/corpus-manifest.txt;--checkis cleanNotes for reviewers
union_declared_property_namesand its two call sites insrc/analysis.rs: the reconciliation at the end ofanalyze_allof_composition, and the end ofanalyze_object_with_variants. Then the new fixture.$refbranch targets when they aren't cached yet, the same waymerge_analyzed_object_propertiesresolves references. Without that,$ref-only unions report no declared names.additional_propertiesmap only to hold the placeholders. Once those placeholders go, it returns to closed, unless the schema declaresadditionalPropertiesor its examples orminProperties/maxPropertiesneed the map.DnsRecordsARecord,DnsRecordsMXRecordand so on, without patching the spec.