OpenAPITools / OpenAPITools/openapi-generator
[REQ][swift6] Option to mark generated declarations nonisolated for projects using default MainActor isolation
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 26.8k
- Forks
- 7.7k
- PR merge metrics
- PR metrics pending
Description
Is your feature request related to a problem? Please describe.
Swift 6.2 lets a module opt into main-actor isolation by default (SE-0466, -default-isolation MainActor; in Xcode 26 the SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor build setting, which the new-project template enables). Under that setting, every top-level declaration without an explicit isolation is inferred @MainActor, including the public struct / public enum models the swift6 generator emits, their Codable conformances, and the extension blocks it writes for them. The generated models then cannot be used from any nonisolated context, which is where decoding normally happens (a URLSession completion, an actor-based API client, a background Task). The diagnostics take the form (Xcode 26, Swift 6.2):
conformance of 'Foo' to protocol 'Decodable' crosses into main actor-isolated code and can cause data races
main actor-isolated initializer 'init(from:)' cannot be used to satisfy nonisolated requirement from protocol 'Decodable'
Describe the solution you'd like
A swift6 generator option, for example nonisolatedModels (boolean), that when enabled emits:
public nonisolated struct Foo: Codable, …/public nonisolated enum Foo: String, …for every top-level modelnonisolated extension Foo: …for every conformance extension the generator writes (e.g. theCaseIterableDefaultsLast/UnknownCaseCheckableextensions produced underenumUnknownDefaultCase, and theoneOfenum wrappers)- the same on the
Infrastructure/*.swiftprotocols and their default-implementation extensions, since anonisolatedtype cannot satisfy a main-actor-isolated protocol requirement, nor take a main-actor default implementation as its witness
nonisolated extension requires Swift 6.2, so the option should probably be documented as requiring a Swift 6.2 toolchain, or emit per-member nonisolated when it is off.
Always emitting nonisolated (without the config option) would also be correct for these types, since it changes nothing for consumers on the default isolation.
Describe alternatives you've considered
additionalModelObjectAttributes: this hook inserts text on the modelstruct/enumline, but it does not reach theoneOfwrapper enums, inline property enums, or the conformanceextensionblocks, and it cannot touch theInfrastructureprotocols. So a project cannot get a compiling result from it alone.- A textual post-pass over the generated files (what we do today): a regex rewriting
^public (struct|enum)and^extension, plus a hand-written copy of the twoInfrastructureprotocols withnonisolatedadded. It works, but it is fragile against template changes. - Wrapping every use of a model in
MainActor.runor making the API client@MainActor: pushes decoding onto the main thread, which incurs unnecessary runtime costs.
Additional context
This is the next step after #20057: that issue made the models Sendable so they can cross an actor boundary; default MainActor isolation additionally pins them to one unless they are declared nonisolated. The generated code is plain value types with no shared mutable state, so there is no reason for it to carry actor isolation. Marking the declarations nonisolated is the correct annotation regardless of the consumer's default-isolation setting, and it is a no-op for modules that keep the Swift 6.0/6.1 default (nonisolated).
- SE-0466 "Control default actor isolation inference": https://github.com/swiftlang/swift-evolution/blob/main/proposals/0466-control-default-actor-isolation.md
- Xcode 26 enables
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActorfor new app targets, so this will affect a growing share of swift6 generator users.
Reproduction
Generate any spec with -g swift6 --global-property models, add the output to an app target with SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor and SWIFT_VERSION = 6, and decode a model from a nonisolated function:
nonisolated func decode(_ data: Data) throws -> Pet {
try JSONDecoder().decode(Pet.self, from: data) // error: main actor-isolated initializer 'init(from:)' …
}
Generator version: 7.25.0.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the swift6 generator entry point using -g swift6 --global-property models, then inspect the templates that emit model declarations, conformance extensions, and Infrastructure/*.swift protocols. Reproduce the issue with SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor and a nonisolated decode function; done means the option produces nonisolated models, extensions, protocols, and default implementations that compile under Swift 6.2.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- openapi, swift
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100