Continuing the discussion from Transitioning a lazy sequence to a collection:
I'm writing this in anger. I searched for the phrase in the subject in case anyone had a solution. Turns out, I already asked the question (at the above link), for the same kind of type! The question was never answered, so I need it here.
What causes this problem; is there some cache in Xcode or the Swift compiler that gets fried? Cleaning the build materials doesn't seem to purge the problem. It's a worse version of a problem I've seen before; usually the compiler will add protocol stubs for you, but sometimes it gets stuck on members you've already added. Now it sometimes gives up on advising you what's wrong.
Here's the type:
public struct LazyDeduplicationSequence<Base: Sequence> {
@usableFromInline
let base: Base
@usableFromInline
let areEquivalent: (Base.Element, Base.Element) -> Bool
@usableFromInline
init(_ base: Base, by areEquivalent: @escaping (Base.Element, Base.Element) -> Bool) {
self.base = base
self.areEquivalent = areEquivalent
}
}
extension LazyDeduplicationSequence: Sequence {
public typealias Iterator = LazyDeduplicationIterator<Base.Iterator>
public typealias Element = Iterator.Element
public __consuming func makeIterator() -> Iterator {
return LazyDeduplicationIterator(base.makeIterator(), by: areEquivalent)
}
@inlinable
public var underestimatedCount: Int {
return base.underestimatedCount.signum()
}
}
extension LazyDeduplicationSequence: LazySequenceProtocol {}
public typealias LazyDeduplicationCollection<T: Collection> = LazyDeduplicationSequence<T>
extension LazyDeduplicationSequence: Collection where Base: Collection { // ERROR HERE
public typealias SubSequence = LazyDeduplicationSequence<Base.SubSequence>
public struct Index: Comparable {
let isoRange: Range<Base.Index>
public static func < (lhs: Index, rhs: Index) -> Bool {
return lhs.isoRange.lowerBound < rhs.isoRange.lowerBound
}
}
public var startIndex: Index {
let start = base.startIndex
guard let firstValue = base.first else { return endIndex }
let end = base.firstIndex { !areEquivalent($0, firstValue) } ?? base.endIndex
return Index(isoRange: start..<end)
}
public var endIndex: Index {
return Index(isoRange: base.endIndex..<base.endIndex)
}
public var isEmpty: Bool { return base.isEmpty }
public func index(after i: Index) -> Index {
let nextStart = i.isoRange.upperBound
precondition(i.isoRange.lowerBound < base.endIndex)
guard nextStart < base.endIndex else { return endIndex }
let nextValue = base[nextStart]
let nextEnd = base[nextStart...].firstIndex { !areEquivalent($0, nextValue) } ?? base.endIndex
return Index(isoRange: nextStart..<nextEnd)
}
public subscript(position: Index) -> Element {
return base[position.isoRange.lowerBound]
}
public subscript(bounds: Range<Index>) -> SubSequence {
return LazyDeduplicationSequence<Base.SubSequence>(base[bounds.lowerBound.isoRange.lowerBound ..< bounds.upperBound.isoRange.upperBound], by: areEquivalent)
}
}
extension LazyDeduplicationSequence.Index: Hashable where Base.Index: Hashable {}
The error at the start of the Collection
extension block is:
Type 'LazyDeduplicationSequence<Base>' does not conform to protocol 'Collection'
Am I triggering some bug?