Right, there's already precedent for protocols being able to affect the isolation of the type. This builds on this precedent, but definitely makes it more complicated.
The general form looks like the issue I referenced, i.e.,
// <<< MyLibrary.swift
public protocol LibraryProtocol: SendableMetaType { }
// <<< ClientModule.swift (MainActor-isolated by default)
import MyLibrary
// ClientType is MainActor isolated.
// ❌ This will create compiler errors when the
// client module wants to use library features.
struct ClientType: LibraryProtocol { }
This came up immediately with CodingKeys
, whether compiler-synthesized or not:
struct S: Codable {
var a: Int
// error: CodingKeys inferred to `@MainActor`, which makes the conformance
// to CodingKey main-actor-isolated and then fails (because the requirements
// need to be nonisolated).
enum CodingKeys: CodingKey {
case a
}
}
There have been some examples from uses of Apple SDKs as well. For example, any use of the Transferable
protocol effectively needs a nonisolated type.
And SwiftData's @Model
is meant for nonisolated types, because the keypaths formed to reference members of a model type need to be Sendable
. This shows up, for example, when using them with Foundation's #Predicate
:
@Model
final class Item {
var timestamp: Date
init(timestamp: Date) {
self.timestamp = timestamp
}
var isTrue = false
static let predicate = {
#Predicate<Item> {
$0.isTrue == true // error here because isTrue is main-actor-isolated
}
}()
}
I agree that we would benefit greatly from tooling that indicated the isolation of various language entities (conformances, types, closures, etc.).
Doug