fix(swift): allow Sendable conformance with objective-c-support#3017
Merged
Conversation
getProtocolsArray unconditionally dropped Sendable whenever objcSupport was enabled, even for enums and structs that have no NSObject/objc interop concern. Drop that guard, and for classes emit `final` (Swift requires NSObject subclasses to be final and immutable to be Sendable) whenever sendable is on and properties are immutable. Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.com>
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.
Bug
With
--sendable --objective-c-support, generated Swift types lostSendableconformance entirely — even enums, which have no NSObject/Objective-C interop concern at all.Repro (from issue #2781, using the maintainer triage's schema/flags):
Before:
@objcMembers class Example: NSObject, Codable { ... }andenum Fruit: String, Codable { ... }— zero occurrences ofSendable.Without
--objective-c-support, the same input correctly producedclass Example: Codable, Sendableandenum Fruit: String, Codable, Sendable.Root cause
getProtocolsArrayinpackages/quicktype-core/src/language/Swift/SwiftRenderer.tsunconditionally droppedSendablewheneverobjcSupportwas enabled, regardless of declaration kind (class/struct/enum). Enums and structs have no NSObject interop concern, so the guard was over-broad. For classes, Swift does allowSendableconformance on anNSObjectsubclass provided the class isfinaland has only immutable,Sendablestored properties.Fix
!this._options.objcSupportguard ingetProtocolsArray, soSendableis added whenever--sendableis set and (for classes) properties are immutable — independent ofobjcSupport.finalwheneversendableis on and properties are immutable (in addition to the existingfinalClassesoption), since Swift requiresNSObjectsubclasses to befinalto conform toSendable.--mutable-propertiesremain non-Sendable/non-final, matching existing (correct) behavior without--objective-c-support.Test coverage
Added a new fixture,
swift-sendable-objective-c(test/languages.ts/test/fixtures.ts), that generates Swift with--sendable --struct-or-class class --objective-c-support(plus astruct-or-class: structvariant viaquickTestRendererOptions) and runs a small verification script (test/fixtures/swift/verify-sendable.cjs) asserting every generatedclass/struct/enumdeclaration includesSendable, and thatSendableclasses are emitted@objcMembers final class.Real
swiftccompilation isn't available in this environment (and the existingswift/schema-swiftfixtures are already disabled in CI'stest-pr.yamldue to a pre-existing "pgp issue"), so this fixture verifies the generated source text directly rather than compiling/running it, following the sameincludeJSON/custom-compileCommandpattern already used elsewhere intest/languages.ts(e.g. thenbl-stats.json-scoped fixtures).Verification performed locally
Generated type is not Sendable) against the pre-fix renderer, and passes after the fix.QUICKTEST=true FIXTURE=swift-sendable-objective-c script/testpasses.npm run test:unit— 169/169 tests pass.npm run lint(biome) — clean.npm run build— passes.Fixes #2781
🤖 Generated with Claude Code