Swift带关联类型协议添加约束扩展被编译器忽略是bug还是特性?
问题结论
这是Swift 5.5及更早版本编译器的已知Bug,并非官方设计的语言特性。
原因说明
两个写法的核心差异在于扩展中方法的返回值声明方式,触发了老版本编译器类型推导的逻辑漏洞:
- 第一种写法中,扩展内的
node方法返回值硬编码为String?,和协议定义中关联类型绑定的Element?写法不同。此时Swift 5.5及更早版本的编译器会错误地跳过扩展的where Element == String约束校验,直接将这个方法判定为协议的全局默认实现,进而推导Doo的Element关联类型就是String,最终错误地判定Doo符合协议要求,没有抛出编译错误。 - 第二种写法中,扩展内的
node方法返回值严格遵循协议定义写为Element?,此时编译器可以正确识别扩展的约束条件,不会将这个方法视为无差别的默认实现,因此会正确抛出Doo未实现协议要求的错误。
修复情况
该Bug已经在Swift 5.6(对应Xcode 13.3及更高版本)中被修复。升级开发环境后,第一种写法也会和第二种写法一样抛出预期的编译错误,不会再出现约束被忽略的问题。
你可以在新版本环境下验证第一种写法,会得到标准的协议不兼容报错:
Type 'Doo' does not conform to protocol 'Arr'
内容的提问来源于stack exchange,提问作者sunny
相关产品推荐
相关产品推荐

