Skip to content

Commit 3f4c9f7

Browse files
committed
Make Span conform to Sequence
Still only with copyable elements, but this allows Span iteration, along with generic sequence algorithms (provided they use the new borrowing iterator).
1 parent 21dae8e commit 3f4c9f7

File tree

3 files changed

+63
-4
lines changed

3 files changed

+63
-4
lines changed

stdlib/public/core/BorrowingIteratorProtocol.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,9 @@ extension Span: BorrowingIteratorProtocol where Element: ~Copyable {
149149
}
150150

151151
@available(SwiftStdlib 6.3, *)
152-
extension Span /*: Sequence /* where Element: ~Copyable */ */ {
152+
extension Span: Sequence /* where Element: ~Copyable */ {
153+
public typealias Iterator = NeverIterator<Element>
154+
153155
@_alwaysEmitIntoClient
154156
@_lifetime(borrow self)
155157
public func makeBorrowingIterator() -> Span<Element> {

stdlib/public/core/Sequence.swift

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ extension Sequence where BorrowingIterator == BorrowingIteratorAdapter<Iterator>
493493
}
494494

495495
@available(SwiftStdlib 6.3, *)
496-
extension Sequence where Iterator == NeverIterator<Element> {
496+
extension Sequence where Iterator == NeverIterator<Element>, Self: ~Copyable & ~Escapable {
497497
public func makeIterator() -> Iterator {
498498
fatalError("Attempt to iterate using a NeverIterator")
499499
}
@@ -711,6 +711,40 @@ extension DropWhileSequence: Sequence {
711711
// Default implementations for Sequence
712712
//===----------------------------------------------------------------------===//
713713

714+
extension Sequence where Self: ~Copyable & ~Escapable {
715+
@inlinable
716+
public var underestimatedCount: Int {
717+
return 0
718+
}
719+
720+
@inlinable
721+
@inline(__always)
722+
public func _customContainsEquatableElement(
723+
_ element: Iterator.Element
724+
) -> Bool? {
725+
return nil
726+
}
727+
728+
@inlinable
729+
@safe
730+
public func withContiguousStorageIfAvailable<R>(
731+
_ body: (UnsafeBufferPointer<Element>) throws -> R
732+
) rethrows -> R? {
733+
return nil
734+
}
735+
736+
public __consuming func _copyContents(
737+
initializing buffer: UnsafeMutableBufferPointer<Element>
738+
) -> (Iterator, UnsafeMutableBufferPointer<Element>.Index) {
739+
fatalError("_copyContents on a ~Copyable/~Copyable sequence")
740+
}
741+
742+
@inlinable
743+
public __consuming func _copyToContiguousArray() -> ContiguousArray<Element> {
744+
fatalError("_copyToContiguousArray on a ~Copyable/~Escapable sequence")
745+
}
746+
}
747+
714748
extension Sequence {
715749
/// Returns an array containing the results of mapping the given closure
716750
/// over the sequence's elements.

test/stdlib/Span/SpanTests.swift

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ suite.test("Span Sendability")
609609
}
610610

611611
@available(SwiftStdlib 6.3, *)
612-
extension Sequence { // Copyable only
612+
extension Sequence where Self: ~Copyable & ~Escapable { // Copyable elements only
613613
func collectViaBorrowing() -> [Element] {
614614
var borrowIterator = makeBorrowingIterator()
615615
var result: [Element] = []
@@ -624,6 +624,25 @@ extension Sequence { // Copyable only
624624
}
625625
}
626626

627+
@available(SwiftStdlib 6.3, *)
628+
func elementsEqual<S1: Sequence, S2: Sequence>(
629+
_ lhs: borrowing S1,
630+
_ rhs: borrowing S2
631+
) -> Bool
632+
where S1.Element: Equatable, S2.Element == S1.Element,
633+
S1: ~Escapable & ~Copyable, S2: ~Escapable & ~Copyable
634+
{
635+
var iter1 = lhs.makeBorrowingIterator()
636+
var iter2 = rhs.makeBorrowingIterator()
637+
while true {
638+
let el1 = iter1.nextSpan(maximumCount: 1)
639+
let el2 = iter2.nextSpan(maximumCount: 1)
640+
if el1.isEmpty && el2.isEmpty { return true }
641+
if el1.isEmpty || el2.isEmpty { return false }
642+
if el1[0] != el2[0] { return false }
643+
}
644+
}
645+
627646
suite.test("BORROWING")
628647
.require(.stdlib_6_3).code {
629648
guard #available(SwiftStdlib 6.3, *) else {
@@ -635,7 +654,11 @@ suite.test("BORROWING")
635654
let arrayCollected = array.collectViaBorrowing()
636655
expectEqual(array, arrayCollected)
637656

657+
let span = array.span
658+
let spanCollected = span.collectViaBorrowing()
659+
expectTrue(elementsEqual(span, spanCollected))
660+
638661
let inline: [8 of Int] = [1, 2, 3, 4, 5, 6, 7, 8]
639662
let inlineCollected = inline.collectViaBorrowing()
640-
expectEqualSequence(inline, inlineCollected)
663+
expectTrue(elementsEqual(inline, inlineCollected))
641664
}

0 commit comments

Comments
 (0)