Skip to content

[swift5] fix: reserve type names the generated client declares or uses from Foundation - #24870

Open
wiebren wants to merge 1 commit into
OpenAPITools:masterfrom
wiebren:fix/swift5-reserve-template-colliding-type-names
Open

[swift5] fix: reserve type names the generated client declares or uses from Foundation#24870
wiebren wants to merge 1 commit into
OpenAPITools:masterfrom
wiebren:fix/swift5-reserve-template-colliding-type-names

Conversation

@wiebren

@wiebren wiebren commented Sep 4, 2026

Copy link
Copy Markdown

A spec that declares a schema named after a type the generated client itself declares — or
after a Foundation type the client's own support files use unqualified — generates swift5
code that cannot compile. Two examples from a real production spec:

A schema named Locale ("a locale that can be used in brand templates") generates
Models/Locale.swift, and inside the generated module that struct wins name resolution
over Foundation.Locale. The client's own support files then stop compiling:

OpenISO8601DateFormatter.swift:15:28: error: cannot assign value of type
'PetstoreClient.Locale' to type 'Foundation.Locale'
        formatter.locale = Locale(identifier: "en_US_POSIX")

A schema named ValidationError generates a struct that collides with the generic
ValidationError<T> that Validation.swift ships in the same module:

Models/ValidationError.swift:13:15: error: invalid redeclaration of 'ValidationError'

The cause

Swift5ClientCodegen.reservedWords already exists for exactly this: ErrorResponse and
Response head the list as "name used by swift client", and URL/Data are reserved as
"commonly-used Foundation types". But the list was never completed — none of the
Validation.swift names, none of the other support-file classes (CodableHelper,
Configuration, RequestBuilder, …), and none of the other Foundation types the support
files reference unqualified (Locale, DateFormatter, TimeZone, URLSession, …) are in
it.

The fix

Complete reservedWords along the two principles the list already encodes, derived by
auditing every swift5 template:

  1. every type the generated code declares at module scope (support files plus the
    urlsession/alamofire/vapor library implementations) — a model with such a name is an
    invalid redeclaration of the client's own type;
  2. every Foundation/stdlib type those templates reference unqualified — a model with
    such a name shadows the real type inside the module and breaks the client's own code
    (the Locale case above).

A model with a reserved name is renamed Model<Name> (ModelLocale,
ModelValidationError), which is the established mechanism: it is exactly what a model
named Response or ErrorResponse already gets today. Naming impact: specs that
declare models with these names (e.g. Configuration, ValidationError) will see those
models renamed with the Model prefix — but today every one of those specs generates code
that does not compile at all, so this cannot break a working setup.

Deliberately not added, to keep the change scoped:

  • names in languageSpecificPrimitives (Date, UUID, Decimal, AnyCodable,
    OpenAPIDateWithoutTime): toModelName intentionally maps these onto the primitive
    types, and existing tests pin that behavior;
  • types from third-party modules (Alamofire's Session/DataRequest, Vapor's
    ClientResponse, PromiseKit's Promise, …): the same shadowing disease exists there,
    but those names only matter for one library flavor, and Swift.Result shows the
    template-side alternative (qualifying the reference) that would fix them without
    renaming anyone's models — happy to do either in a follow-up if there is interest.

The swift6 generator has the identical list with the identical gap; the same additions
apply there and I can extend this PR or follow up, whichever you prefer.

Tests / verification

  • Swift5ClientCodegenTest#reservedTypeNamesDeclaredByClientTest and
    #reservedFoundationTypeNamesTest cover both groups; they fail on master and pass with
    the fix. Full swift5 test classes pass.
  • ./bin/generate-samples.sh ./bin/configs/swift5-*.yaml produces no sample diff: no
    petstore sample declares a model with any of the reserved names.
    ./bin/utils/export_docs_generators.sh updates the reserved-words list in
    docs/generators/swift5.md (committed here).
  • Verified end to end with a minimal spec declaring Locale and ValidationError schemas:
    on master the generated client fails with the two errors quoted above; with this fix it
    generates ModelLocale.swift/ModelValidationError.swift, all references follow, and
    swift build succeeds in a swift:6.1 container.

Existing upstream issues: none found for this shadowing
(searched Locale swift, Foundation.Locale, OpenISO8601DateFormatter,
swift ValidationError). #9903 (closed) was the same class of bug for a query parameter
named path; #22073 is a different swift6 collision class (property casing).

PR checklist

  • Read the contribution guidelines.
  • Built the project and updated samples (./bin/generate-samples.sh ./bin/configs/swift5-*.yaml — no diff; ./bin/utils/export_docs_generators.sh
    docs/generators/swift5.md updated and committed).
  • Technical committee: @4brunu

Generated with Claude Code


Summary by cubic

Fixes the swift5 generator so schemas named after types the generated client declares or uses from Foundation no longer produce uncompilable code. Models like Locale or ValidationError are now renamed ModelLocale/ModelValidationError, the same mechanism already used for Response and ErrorResponse.

Naming impact

  • Specs declaring models with any newly reserved name (e.g., Configuration, ValidationError) will see them renamed with a Model prefix.
  • Those specs currently generate code that doesn't compile at all, so this cannot break a working setup.

Written for commit c1a1280. Summary will update on new commits.

Review in cubic

…s from Foundation

A schema named Locale generates Models/Locale.swift, which shadows
Foundation.Locale inside the generated module and breaks the client's own
OpenISO8601DateFormatter/Extensions support files; a schema named
ValidationError is an invalid redeclaration of Validation.swift's generic
ValidationError<T>. reservedWords already covers ErrorResponse/Response and
URL/Data for exactly this reason, but not the rest of the names the
generated code declares at module scope or references unqualified from
Foundation. Complete the list so such models are renamed Model<Name>, the
same mechanism a model named Response already gets.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CxDNCjqJycKTfzVWg2SeTJ

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 3 files

Re-trigger cubic

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.

1 participant