Annotate thread safe types with NS_SWIFT_SENDABLE
Nobody has claimed this yet.
- Dominant language
- Objective-C
- Stars
- 2k
- Forks
- 867
- Avg merge
- 4d 48m
- Merged PRs (30d)
- 1
Description
Problem
I ran into a problem migrating code to Swift 6., because the compiler cannot be certain that OIDServiceConfiguration is used in a thread safe manner.
Consider the following function:
func discoverConfiguration(discoveryUrl: URL) async throws -> OIDServiceConfiguration {
try await withCheckedThrowingContinuation { continuation in
OIDAuthorizationService.discoverConfiguration(forDiscoveryURL: discoveryUrl) { config, _ in
if let config {
continuation.resume(returning: config) // Error: Sending 'config' risks causing data races
// Task-isolated 'config' is passed as a 'sending' parameter; Uses in callee may race with later task-isolated uses
} else {
// ...
}
}
}
}
Because OIDServiceConfiguration is returned via callback closure, the compiler has to assume that it may be used by the sending function (+[OIDAuthorizationService discoverConfiguration]) even after the closure is called. Because OIDServiceConfiguration is not declared Sendable this results in a compile error (see inline comments).
Solution
Annotate OIDServiceConfiguration with NS_SWIFT_SENDABLE.
This makes the assumption that OIDServiceConfiguration is in fact thread safe. Looking at the code, I see only one point which might make the class not thread safe: OIDServiceConfiguration holds a reference to OIDServiceDiscovery which in turn holds a reference to NSDictionary (NSDictionary *_discoveryDictionary) which may contain non thread safe objects. But in real life those would only be PODs (String, Int) which are thread safe, correct?
Ideally, all thread safe types in AppAuth would be annotated with NS_SWIFT_SENDABLE.
Workaround
Wrap the OIDServiceConfiguration object into an @unchecked Sendable object to send it to the continuation. This disables the compiler checks.
Additional Information
No compile error with Swift 5 – not even with complete concurrency checks enabled.
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 OIDServiceConfiguration, OIDServiceDiscovery, and the OIDAuthorizationService.discoverConfiguration callback described in the issue. Review whether the referenced discovery data and other thread-safe types support NS_SWIFT_SENDABLE, then identify the relevant SDK declarations to annotate. Done means Swift 6 concurrency checking accepts the configuration flow without the unchecked-Sendable workaround.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- objective-c, swift
- Domain
- authentication, mobile
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100