Skip to content

Emit a clear error instead of crashing on duplicate generated schema names - #939

Merged
simonjbeaumont merged 2 commits into
apple:mainfrom
shin4141:codex/apple-854-attributed-repair
Aug 20, 2026
Merged

Emit a clear error instead of crashing on duplicate generated schema names#939
simonjbeaumont merged 2 commits into
apple:mainfrom
shin4141:codex/apple-854-attributed-repair

Conversation

@shin4141

Copy link
Copy Markdown
Contributor

Summary

When the idiomatic naming strategy maps distinct OpenAPI component keys to the same generated Swift type name, schema translation currently reaches Dictionary(uniqueKeysWithValues:) in recursive-type boxing and traps. This change detects duplicate generated top-level schema names before boxing and emits a deterministic error diagnostic with the documented defensive naming and nameOverrides resolution paths.

The defensive lookup in translateBoxedTypes keeps execution from reaching the duplicate-key dictionary initializer when a non-throwing diagnostic collector continues after the error. Duplicate basenames in different namespaces remain valid.

Fixes #854.

Prior work and attribution

This continues the work from #907/#914 by Aditya Singh and incorporates the review feedback left there.

The original issue and reproduction were reported by @marknefedov in #854. Aditya Singh (@adityasingh2400) implemented the substantial prior repair in #907 and #914. The placement in translateSchemas, keeping translateBoxedTypes focused on boxing, the single plural diagnostic path, and the A.T / B.T namespace countercase follow review direction from @simonjbeaumont on #914.

The bug report and repair lineage are not original to this patch; this submission does not claim discovery or sole authorship.

Verification

  • Apple Swift 6.3.2 / macOS SDK 26.5 build 25F70: frozen baseline collision probe RED with exit 133 and Fatal error: Duplicate values for key: 'NullTime'.
  • The identical collision probe after applying this exact patch completes with one error diagnostic and exit 0.
  • A.T / B.T repository-native generated identities A.TPayload / B.TPayload: exit 0, no diagnostic.
  • Test_translateSchemas: throwing collector, non-throwing collector, deterministic multiple collisions, and namespace countercase coverage.
  • Previously verified affected offline surface: 312 tests, 1 expected pre-existing skip, 0 failures.
  • Strict swift-format lint and git diff --check: exit 0.

Scope

Exactly three files change: two _OpenAPIGeneratorCore implementation files and one focused test file. No public API or new architecture is introduced.

Continue the work from apple#907 and apple#914 with the reviewed placement, one-path diagnostic, and namespace regression coverage.

Co-authored-by: Aditya Singh <adisin650@gmail.com>
Comment on lines +28 to +30
let nodeLookup = nodes.reduce(into: [String: DeclarationRecursionDetector.Node]()) { lookup, node in
if lookup[node.name] == nil { lookup[node.name] = node }
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let nodeLookup = nodes.reduce(into: [String: DeclarationRecursionDetector.Node]()) { lookup, node in
if lookup[node.name] == nil { lookup[node.name] = node }
}
let nodeLookup = Dictionary(nodes.map { ($0.name, $0) }, uniquingKeysWith: { first, _ in first })

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks — updated the lookup to use Dictionary(_:uniquingKeysWith:) as suggested. Re-ran Test_translateSchemas (5 tests, 0 failures), the affected test surface (312 tests, 1 expected skip, 0 failures), strict swift-format, and git diff --check.

@simonjbeaumont simonjbeaumont left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. Mostly looks good. Made a suggestion to the dictionary build which seems a little obfuscated right now.

@simonjbeaumont simonjbeaumont added the 🔨 semver/patch No public API change. label Aug 20, 2026

@simonjbeaumont simonjbeaumont left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@simonjbeaumont
simonjbeaumont enabled auto-merge (squash) August 20, 2026 16:11
@simonjbeaumont
simonjbeaumont merged commit 7f0ec74 into apple:main Aug 20, 2026
49 of 50 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 semver/patch No public API change.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crash on duplicate schema name with idiomatic naming strategy

2 participants