Swift 6协议继承中与Main Actor相关的异常行为问询
核心原因在于系统提供的Codable等基础协议带有隐式的@nonisolated(unsafe)标记,而自定义非隔离协议仅为普通的nonisolated,这两种标记在Swift 6的协议组合隔离规则中优先级完全不同。
具体场景拆解
自定义NonIso协议 + Main协议组合
自定义的NonIso协议只是普通的nonisolated声明,在项目默认Main Actor的Swift 6环境中,协议组合时Main Actor的隔离标注优先级更高,所以Foo协议默认继承Main隔离;手动添加nonisolated可以覆盖这个默认规则,表现符合预期。
示例代码:nonisolated protocol NonIso {} @MainActor protocol Main {} // 默认是@MainActor隔离,标记nonisolated后变为非隔离 protocol Foo: NonIso, Main {} // 或 nonisolated protocol Foo: NonIso, Main {}Codable协议 + Main协议组合
Codable作为Swift系统核心协议,被苹果隐式添加了@nonisolated(unsafe)标记。这种标记的特殊之处在于:它会强制覆盖所有其他隔离标注的优先级——哪怕你给Foo协议手动加上@MainActor,也会被Codable的@nonisolated(unsafe)强制拉为非隔离状态。这就导致遵循Foo的结构体(默认继承项目Main隔离)出现数据竞争警告:结构体的隔离上下文和协议要求的非隔离上下文冲突。换回NonIso协议后恢复正常
再次使用普通的nonisolated自定义协议时,协议组合的优先级回到「默认Main隔离优先」,所以Foo协议重新恢复为Main隔离状态。
补充说明
Swift 6给Codable、Equatable、Hashable这类基础协议添加@nonisolated(unsafe),是为了保证兼容性——这些协议广泛用于各种非隔离场景(比如数据模型、序列化),如果被项目默认的Main Actor隔离强制影响,会导致大量现有代码出现编译错误或运行时问题。而自定义协议没有这种特殊处理,完全遵循用户声明和项目默认隔离的规则。
内容的提问来源于stack exchange,提问作者HL666

