为什么我必须在我的自定义 RangeReplaceableCollection 中实现 append<S: Sequence>(contentsOf newElements: S)
Why do I have to implement append<S: Sequence>(contentsOf newElements: S) in my custom RangeReplaceableCollection
我目前正在尝试将自定义集合类型更新到 Swift 4.1。
但是,当我遵守文档并实现 Collection
和 RangeReplaceableCollection
的所有要求时,Xcode 仍然抱怨我的类型不符合 RangeReplaceableCollection
.
Here's an mcve 问题(由 Hamish 慷慨提供,谢谢你:)
class Foo<Element : AnyObject> {
required init() {}
private var base: [Element] = []
}
extension Foo : Collection {
typealias Index = Int
var startIndex: Index {
return base.startIndex
}
var endIndex: Index {
return base.endIndex
}
func index(after i: Index) -> Index {
return base.index(after: i)
}
subscript(index: Index) -> Element {
return base[index]
}
}
extension Foo : RangeReplaceableCollection {
func replaceSubrange<C : Collection>(
_ subrange: Range<Index>, with newElements: C
) where Element == C.Element {}
}
According to the documentation,代码应该编译:
To add RangeReplaceableCollection conformance to your custom
collection, add an empty initializer and the replaceSubrange(_:with:)
method to your custom type. RangeReplaceableCollection provides
default implementations of all its other methods using this
initializer and method.
不幸的是,事实并非如此。相反,Xcode 发出以下错误消息:
// error: type 'Foo<Element>' does not conform to protocol 'RangeReplaceableCollection'
// extension Foo : RangeReplaceableCollection {
// ^
// Swift.RangeReplaceableCollection:5:26: note: candidate has non-matching type '<Self, S> (contentsOf: S) -> ()' [with SubSequence = Foo<Element>.SubSequence]
// public mutating func append<S>(contentsOf newElements: S) where S : Sequence, Self.Element == S.Element
// ^
// Swift.RangeReplaceableCollection:9:26: note: protocol requires function 'append(contentsOf:)' with type '<S> (contentsOf: S) -> ()'; do you want to add a stub?
// public mutating func append<S>(contentsOf newElements: S) where S : Sequence, Self.Element == S.Element
//
为了确保这不是文档中的错误,我检查了 the source code of Swift 4.1 并在 RangeReplaceableCollection.swift 的第 442-452 行中找到了 func append<S>(contentsOf newElements: S) where S: Sequence, Element == S.Element
的默认实现:
@_inlineable
public mutating func append<S : Sequence>(contentsOf newElements: S) where S.Element == Element {
let approximateCapacity = self.count + numericCast(newElements.underestimatedCount)
self.reserveCapacity(approximateCapacity)
for element in newElements {
append(element)
}
}
问题:
- 尽管提供了默认实现,但为什么 Xcode 要求实现此功能?
- 如何编译我的代码?
尽管提供了默认实现,但为什么 Xcode 要求实现此功能?
这是由于 Swift 4.1 中引入的 TypeChecker 中的一个错误:
[SR-7429]: Cannot conform a non-final class to a protocol with a defaulted requirement with a generic placeholder constrained to an associated type
如何编译我的代码?
在错误修复之前,目前有三种方法可以编译它。
实现这两个函数:
required init<S : Sequence>(_ elements: S) where Element == S.Element {}
func append<S : Sequence>(contentsOf newElements: S) where Element == S.Element
将class标记为final
。
将集合类型实现为 struct
。为此,必须删除 required init() {}
。
我目前正在尝试将自定义集合类型更新到 Swift 4.1。
但是,当我遵守文档并实现 Collection
和 RangeReplaceableCollection
的所有要求时,Xcode 仍然抱怨我的类型不符合 RangeReplaceableCollection
.
Here's an mcve 问题(由 Hamish 慷慨提供,谢谢你:)
class Foo<Element : AnyObject> {
required init() {}
private var base: [Element] = []
}
extension Foo : Collection {
typealias Index = Int
var startIndex: Index {
return base.startIndex
}
var endIndex: Index {
return base.endIndex
}
func index(after i: Index) -> Index {
return base.index(after: i)
}
subscript(index: Index) -> Element {
return base[index]
}
}
extension Foo : RangeReplaceableCollection {
func replaceSubrange<C : Collection>(
_ subrange: Range<Index>, with newElements: C
) where Element == C.Element {}
}
According to the documentation,代码应该编译:
To add RangeReplaceableCollection conformance to your custom collection, add an empty initializer and the replaceSubrange(_:with:) method to your custom type. RangeReplaceableCollection provides default implementations of all its other methods using this initializer and method.
不幸的是,事实并非如此。相反,Xcode 发出以下错误消息:
// error: type 'Foo<Element>' does not conform to protocol 'RangeReplaceableCollection'
// extension Foo : RangeReplaceableCollection {
// ^
// Swift.RangeReplaceableCollection:5:26: note: candidate has non-matching type '<Self, S> (contentsOf: S) -> ()' [with SubSequence = Foo<Element>.SubSequence]
// public mutating func append<S>(contentsOf newElements: S) where S : Sequence, Self.Element == S.Element
// ^
// Swift.RangeReplaceableCollection:9:26: note: protocol requires function 'append(contentsOf:)' with type '<S> (contentsOf: S) -> ()'; do you want to add a stub?
// public mutating func append<S>(contentsOf newElements: S) where S : Sequence, Self.Element == S.Element
//
为了确保这不是文档中的错误,我检查了 the source code of Swift 4.1 并在 RangeReplaceableCollection.swift 的第 442-452 行中找到了 func append<S>(contentsOf newElements: S) where S: Sequence, Element == S.Element
的默认实现:
@_inlineable
public mutating func append<S : Sequence>(contentsOf newElements: S) where S.Element == Element {
let approximateCapacity = self.count + numericCast(newElements.underestimatedCount)
self.reserveCapacity(approximateCapacity)
for element in newElements {
append(element)
}
}
问题:
- 尽管提供了默认实现,但为什么 Xcode 要求实现此功能?
- 如何编译我的代码?
尽管提供了默认实现,但为什么 Xcode 要求实现此功能?
这是由于 Swift 4.1 中引入的 TypeChecker 中的一个错误:
[SR-7429]: Cannot conform a non-final class to a protocol with a defaulted requirement with a generic placeholder constrained to an associated type
如何编译我的代码?
在错误修复之前,目前有三种方法可以编译它。
实现这两个函数:
required init<S : Sequence>(_ elements: S) where Element == S.Element {}
func append<S : Sequence>(contentsOf newElements: S) where Element == S.Element
将class标记为
final
。将集合类型实现为
struct
。为此,必须删除required init() {}
。