Swift 向具有关联类型的协议添加约束扩展
Swift add constraint extension to Protocol that has an associated type
当我向具有关联类型的协议添加约束扩展时,swift 编译器会忽略我的约束。
当我写的时候:
protocol Arr {
associatedtype Element
func node(_ at: Int) -> Element?
}
extension Arr where Element == String {
func node(_ at: Int) -> String? {
nil
}
}
struct Doo: Arr {
}
Xcode 构建成功,它认为我的 Doo
的 Element
是 String
。它忽略 where Element == String
约束。
当我写的时候:
protocol Arr {
associatedtype Element
func node(_ at: Int) -> Element?
}
extension Arr where Element == String {
func node(_ at: Int) -> Element? { // use Element
nil
}
}
struct Doo: Arr {
}
Xcode 显示错误,正如预期的那样。
这是 Xcode 错误还是 Swift 功能?
Xcode版本:Version 13.1 (13A1030d)
Swift版本:
swift-driver version: 1.26.9 Apple Swift version 5.5.1 (swiftlang-1300.0.31.4 clang-1300.0.29.6)
Target: arm64-apple-macosx12.0
第二种情况的错误是因为Xcode无法推断出元素的类型。如果指定它,所有内容都会编译。
struct Doo: Arr {
typealias Element = String
}
这里发生的是 Swift 如果可以从上下文中提取协议要求,它将很乐意满足协议要求。
例如,假设扩展名不存在,Doo
定义将是这样的:
struct Doo: Arr {
func node(_ at: Int) -> String? {
nil
}
}
,Swift 编译器会愉快地填充 Element
关联类型。
您的第一段代码也会发生类似的情况,Doo
符合 Arr
,并且编译器会找到一个满足所有协议要求的定义。 Swift 不会忽略 Element == String
约束,因为它将它与 Doo
结构相关联。
如果您以类似的方式添加第二个扩展,但对于另一种类型(例如 Int
),您会看到收到预期的错误。发生这种情况是因为编译器无法再推断协议要求。
Swift 编译器急切地从它可以到达的上下文中推断出尽可能多的东西,大多数时候会给出很好的结果,有时不是很好(尤其是在使用闭包时),有时它会给出意想不到的结果(比如这个)。
如果您想确保编译器推断出您想要的类型,解决方案是显式声明所有涉及的类型。
当我向具有关联类型的协议添加约束扩展时,swift 编译器会忽略我的约束。
当我写的时候:
protocol Arr {
associatedtype Element
func node(_ at: Int) -> Element?
}
extension Arr where Element == String {
func node(_ at: Int) -> String? {
nil
}
}
struct Doo: Arr {
}
Xcode 构建成功,它认为我的 Doo
的 Element
是 String
。它忽略 where Element == String
约束。
当我写的时候:
protocol Arr {
associatedtype Element
func node(_ at: Int) -> Element?
}
extension Arr where Element == String {
func node(_ at: Int) -> Element? { // use Element
nil
}
}
struct Doo: Arr {
}
Xcode 显示错误,正如预期的那样。
这是 Xcode 错误还是 Swift 功能?
Xcode版本:Version 13.1 (13A1030d)
Swift版本:
swift-driver version: 1.26.9 Apple Swift version 5.5.1 (swiftlang-1300.0.31.4 clang-1300.0.29.6)
Target: arm64-apple-macosx12.0
第二种情况的错误是因为Xcode无法推断出元素的类型。如果指定它,所有内容都会编译。
struct Doo: Arr {
typealias Element = String
}
这里发生的是 Swift 如果可以从上下文中提取协议要求,它将很乐意满足协议要求。
例如,假设扩展名不存在,Doo
定义将是这样的:
struct Doo: Arr {
func node(_ at: Int) -> String? {
nil
}
}
,Swift 编译器会愉快地填充 Element
关联类型。
您的第一段代码也会发生类似的情况,Doo
符合 Arr
,并且编译器会找到一个满足所有协议要求的定义。 Swift 不会忽略 Element == String
约束,因为它将它与 Doo
结构相关联。
如果您以类似的方式添加第二个扩展,但对于另一种类型(例如 Int
),您会看到收到预期的错误。发生这种情况是因为编译器无法再推断协议要求。
Swift 编译器急切地从它可以到达的上下文中推断出尽可能多的东西,大多数时候会给出很好的结果,有时不是很好(尤其是在使用闭包时),有时它会给出意想不到的结果(比如这个)。
如果您想确保编译器推断出您想要的类型,解决方案是显式声明所有涉及的类型。