在Swift 6中,将默认的Actor隔离设为主Actor之后,出现了与协议符合性相关的异常行为
我有这段代码:
protocol MainP {
func foo()
}
nonisolated protocol NonIsoP {
func bar()
}
struct MainStruct1: MainP {
func foo() {}
}
struct MainStruct2: NonIsoP {
func bar() {}
}
nonisolated struct NonIsoStruct1: MainP {
func foo() {}
}
nonisolated struct NonIsoStruct2: MainP {
@MainActor
func foo() {}
}
nonisolated struct NonIsoStruct3: NonIsoP {
func bar() {}
}
nonisolated struct NonIsoStruct4: NonIsoP {
@MainActor
func bar() {}
}
我创建了一个新项目(我使用Xcode 26.2),把设置改为:
- 默认的actor隔离设为main actor
- Swift语言 = Swift 6
然后只有 NonIsoStruct4 会报错。
对协议 'NonIsoP' 的 'NonIsoStruct4' 的符合性跨入了主actor隔离代码,可能导致数据竞争
然而,我预计 MainStruct2 会因为同样的错误而失败,因为MainStruct2不满足 NonIsoP 的“拥有非隔离foo()”的要求。本来它应该和以下编译错误完全一致:错误“Conformance of [StructType] to protocol [ProtocolType] crosses into main actor isolated code in approachable concurrency”,但不知为何现在就通过了。
解决方案
这在这里有文档:在这里:
SE-0466提供了指定给定模块将对任何未显式声明隔离(或非隔离,通过
nonisolated)的代码推断@MainActor的能力。在一个推断@MainActor的模块中,来自前一节的即将到来的特性InferIsolatedConformances也应被启用。这意味着类型将获得主actor的隔离,并且它们的符合性也将是主actor隔离的,将SE-0466的“主要是单线程”的观点扩展到与通用代码的交互。
所以实际上 MainStruct2 是隐式的一个隔离符合:
@MainActor
struct MainStruct2: @MainActor NonIsoP {
func bar() {}
}
这与 RLActionState 之间唯一的区别在于 RLActionState 已经是主actor隔离,因此我猜编译器只会忽略它,不会将其视为一个隔离的符合,同时也没有考虑它继承自 CustomDebugStringConvertible 的事实。
这个问题似乎已经在这里被报道过:在这里。请关注该问题以获取更多更新。