Skip to content

[swift6] Add nonisolatedModels option for default MainActor isolation - #25004

Merged
4brunu merged 3 commits into
OpenAPITools:masterfrom
danieldickison:swift6-nonisolated-models
Sep 25, 2026
Merged

4brunu merged 3 commits into
OpenAPITools:masterfrom
danieldickison:swift6-nonisolated-models

Conversation

@danieldickison

@danieldickison danieldickison commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

This PR was generated by Claude Code but I've looked through the changes and it all looks reasonable to me.


Fixes #24903

Adds a nonisolatedModels boolean option (default: false) to the swift6 generator.

Swift 6.2 lets a module opt into main-actor isolation by default (SE-0466, -default-isolation MainActor; SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor in Xcode 26). When generated sources are vendored into such a module, every model becomes @MainActor-isolated, so their Codable conformances can't be used from URLSession completions, background tasks, or any other nonisolated context ("conformance of 'Foo' to protocol 'Decodable' crosses into main actor-isolated code").

With nonisolatedModels: true, the generator marks the following nonisolated:

  • model struct/final class/enum declarations (including the objcCompatible NSObject subclasses), and the Identifiable / UnknownCaseCheckable extensions emitted next to them
  • the protocols and helper types models conform to or store: ParameterConvertible, CaseIterableDefaultsLast, UnknownCaseCheckable, NullEncodable, JSONValue, OpenAPIDateWithoutTime, the validation rule structs
  • the ParameterConvertible conformances and the CodingKey / keyed-container extensions in Extensions.swift
  • CodableHelper, OpenAPIMutex and OpenISO8601DateFormatter, which the above depend on

Output is byte-identical when the option is off (all 14 swift6 sample configs were regenerated; only validation, where the option is now enabled, changed). Enabling the option requires a Swift 6.1+ toolchain (nonisolated on types and extensions, SE-0449).

Scope note: the API layer (APIs.swift, URLSessionImplementations.swift, RequestTask) is unchanged and still assumes a nonisolated module. This option targets the model layer, per the issue.

Note on objcCompatible models: the option is isolation-neutral for them. Those classes are already declared @unchecked Sendable with mutable properties, and nonisolated only removes a main-actor guarantee that Objective-C callers never honored anyway. It does not make them more or less thread-safe than they are today; the safe usage pattern (decode, then treat as read-only when shared, or use readonlyProperties) is unchanged.

Testing

  • Swift6* unit tests pass (50 run, 0 failures), including two new generation tests asserting the nonisolated output with the option on and its absence with the option off.
  • Built the regenerated validation sample and the other swift6 samples with Swift 6.4: all 13 directories in the samples-swift6.yaml macOS matrix (alamofireLibrary, apiNonStaticMethod, asyncAwaitLibrary, combineDeferredLibrary, combineLibrary, default, objcCompatible, oneOf, promisekitLibrary, resultLibrary, rxswiftLibrary, urlsessionLibrary, validation) pass swift build.
  • Compiled the validation, petstore-with-fake-endpoints, recursive-models and oneOf outputs with .defaultIsolation(MainActor.self) in a scratch package (API layer excluded): 0 diagnostics in model and support files with the option on. With the option off, the same builds fail with e.g. conformance of 'Banana' to 'Decodable' cannot be used in nonisolated context and conformance of 'EnumClass' to protocol 'CaseIterableDefaultsLast' crosses into main actor-isolated code.
  • ./mvnw verify on modules/openapi-generator: BUILD SUCCESS (checkstyle, jacoco check, javadoc, forbiddenapis all pass); surefire 5134 run, 0 failures, 12 skipped. On my local JDK 25 there are 8 errors in KotlinTestUtilsTest / KotlinSpringServerCodegenTest (the embedded Kotlin compiler can't parse the JDK version string 25.0.3); those two classes pass on JDK 21 (288 run, 0 failures, 0 errors), and this change doesn't touch them.

PR checklist

🤖 Generated with Claude Code


Summary by cubic

Adds a nonisolatedModels option to the swift6 generator so generated sources stay usable when vendored into modules built with Swift 6.2 default MainActor isolation (SE-0466). Fixes #24903.

  • When on, marks model declarations and their Identifiable/UnknownCaseCheckable extensions, supporting protocols and helpers, and objcCompatible classes nonisolated; requires a Swift 6.1+ toolchain.
  • Off by default with byte-identical output; the API layer is unchanged and still assumes a nonisolated module.
  • Enabled in the swift6 validation sample, with generation tests asserting the option's effect on and off, covering enum, oneOf, and objcCompatible models.

Written for commit 37202c0. Summary will update on new commits.

Review in cubic

Adds a `nonisolatedModels` boolean option (default: false) to the swift6
generator. When enabled, generated model structs/classes/enums, the
extensions emitted alongside them, and the supporting protocols and helper
types they conform to or store (ParameterConvertible,
CaseIterableDefaultsLast, UnknownCaseCheckable, NullEncodable, JSONValue,
OpenAPIDateWithoutTime, the validation rule structs, CodableHelper,
OpenAPIMutex, OpenISO8601DateFormatter, and the ParameterConvertible,
CodingKey and Codable container extensions in Extensions.swift) are marked
`nonisolated`. This lets the generated sources be vendored into a module
built with Swift 6.2 default MainActor isolation (SE-0466) while keeping
models decodable and usable off the main actor. Requires a Swift 6.1+
toolchain when enabled; output is unchanged when the option is off.

Enabled in the swift6 validation sample.

Fixes OpenAPITools#24903

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@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.

All reported issues were addressed across 26 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread modules/openapi-generator/src/main/resources/swift6/model.mustache
@4brunu

4brunu commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

Can you please take a look at the comments? Thanks

Review flagged that objcCompatible model classes were left MainActor-isolated
while their Identifiable/UnknownCaseCheckable extensions were marked
nonisolated, which fails to compile under default MainActor isolation. Mark the
objcCompatible class declaration nonisolated too (verified to build with 0
errors), and add tests for top-level, nested and oneOf enums and objcCompatible.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@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.

All reported issues were addressed across 2 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@4brunu
4brunu merged commit 10e6c21 into OpenAPITools:master Sep 25, 2026
30 of 31 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.

[REQ][swift6] Option to mark generated declarations nonisolated for projects using default MainActor isolation

2 participants