Description
Description
I’ve been trying to understand how library code may work with new application targets that use main actor isolation and Swift 6 language mode and came across the following behavior.
Reproduction
Given library code with a basic protocol hierarchy:
protocol P1 { func f() }
protocol P2: P1 {}
And an app using main actor isolation and Swift 6 language mode:
struct S1: P1 { func f() }
struct S2: P2 { func f() }
S1
compiles fine, while S2
fails with:
Conformance of 'S' to protocol 'P2' crosses into main actor-isolated code and can cause data races
Here is a project that reproduces this behavior: MainActorConformances.zip
The error can be worked around with an explicit @MainActor
:
struct S2: @MainActor P2 { func f() }
A similar behavior can be demonstrated with a standard library protocol like Collection
:
struct MyCollection: Collection {
var startIndex: Int { 0 }
var endIndex: Int { 0 }
func index(after i: Int) -> Int { i + 1 }
subscript(offset: Int) -> String { "" }
// Comment the following in and it builds:
// func makeIterator() -> AnyIterator<String> {
// fatalError()
// }
}
Conformance of 'MyCollection' to protocol 'Sequence' crosses into main actor-isolated code and can cause data races
This can also be worked around with explicit @MainActor
, but curiously it can also be worked around with a manual makeIterator
implementation.
Expected behavior
I would hope that @MainActor
would be inferred automatically through the entire hierarchy, especially since an extension macro can apply a conformance but can’t know whether or not it should do so with a specific isolation.
Environment
Apple Swift version 6.2-dev (LLVM 9ae4b59a6edd27c, Swift 9b6c04e)
Target: arm64-apple-macosx15.0
Build config: +assertions
Additional information
Swift forums thread: https://forums.swift.org/t/default-main-actor-isolation-and-protocol-inheritance/80419