Skip to content

Commit a9ff08d

Browse files
committed
Generalize Sequence to be ~Copyable & ~Escapable
This change allows noncopyable and nonescapable Sequence types, with room for generalizing the Element type to be ~Copyable in the future. The new prototype adds a BorrowingIterator associated type to Sequence This commit adds a BorrowingIteratorProtocol for generalized bulk iteration, a BorrowingIteratorAdapter as an implementation of the new Sequence requirement for existing sequences, and a NeverIterator for new noncopyable/nonescapable sequence types. Conformance to Sequence for Span and InlineArray is also included. Issues: - Availability checking must be off due to the availability requirements on the new Sequence.BorrowingIterator associated type - Several existing sequences needed an explicit Element type alias to compile (note that this was during experimentation, so it may be possible to back out these changes) - Some of the default implementations for generalized sequences simply fatal error - InlineArray is a tricky case, due to its conditionally copyable design. It conforms to Sequence unconditionally, so it needs an unconditional implementation of (the original) Iterator associated type. However, when Sequence can use ~Copyable elements, that implementation won't be workable, since (a) it copies the inline array, and (b) it implements the `next() -> Element?` method, which can't return a noncopyable element.
1 parent ff56888 commit a9ff08d

File tree

17 files changed

+293
-71
lines changed

17 files changed

+293
-71
lines changed

benchmark/single-source/DataBenchmarks.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,14 +327,20 @@ let large = sampleData(.large)
327327
let array809 = byteArray(size: 809)
328328

329329
struct Count0<S: Sequence> : Sequence {
330+
@available(macOS 9999, *)
331+
public typealias BorrowingIterator = BorrowingIteratorAdapter<S.Iterator>
332+
330333
let base: S
331334
init (_ base:S) { self.base = base }
332335
func makeIterator() -> S.Iterator { return base.makeIterator() }
333336
var underestimatedCount: Int { return 0 }
334337
}
335338

336339
struct Bytes: Sequence, IteratorProtocol {
337-
let count: Int
340+
@available(macOS 9999, *)
341+
public typealias BorrowingIterator = BorrowingIteratorAdapter<Self>
342+
343+
let count: Int
338344
let exact: Bool
339345
var i: Int = 0
340346
init(count: Int, exact: Bool) {

stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ public enum UnderestimatedCountBehavior {
8383
///
8484
/// This sequence is consumed when its generator is advanced.
8585
public struct MinimalSequence<T> : Sequence, CustomDebugStringConvertible {
86+
public typealias Element = T
87+
8688
public init<S : Sequence>(
8789
elements: S,
8890
underestimatedCount: UnderestimatedCountBehavior = .value(0)

stdlib/private/StdlibUnittest/StdlibUnittest.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2241,7 +2241,8 @@ public enum StdLibVersion: String {
22412241
case stdlib_6_0 = "6.0"
22422242
case stdlib_6_1 = "6.1"
22432243
case stdlib_6_2 = "6.2"
2244-
2244+
case stdlib_6_3 = "6.3"
2245+
22452246
var isAvailable: Bool {
22462247
switch self {
22472248
case .stdlib_5_7:
@@ -2258,6 +2259,8 @@ public enum StdLibVersion: String {
22582259
return if #available(SwiftStdlib 6.1, *) { true } else { false }
22592260
case .stdlib_6_2:
22602261
return if #available(SwiftStdlib 6.2, *) { true } else { false }
2262+
case .stdlib_6_3:
2263+
return if #available(SwiftStdlib 6.3, *) { true } else { false }
22612264
}
22622265
}
22632266
}

stdlib/private/SwiftReflectionTest/SwiftReflectionTest.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,10 @@ internal struct Section {
226226

227227
/// Holds the addresses and sizes of sections related to reflection.
228228
internal struct ReflectionInfo : Sequence {
229+
internal typealias Element = Section?
230+
@available(macOS 9999, *)
231+
internal typealias BorrowingIterator = BorrowingIteratorAdapter<AnyIterator<Section?>>
232+
229233
/// The name of the loaded image.
230234
internal let imageName: String
231235

stdlib/public/Concurrency/Deque/Deque+Collection.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ extension _Deque: Sequence {
1919
// This custom implementation performs direct storage access to eliminate any
2020
// and all index validation overhead. It also optimizes away repeated
2121
// conversions from indices to storage slots.
22+
@available(macOS 9999, *)
23+
internal typealias BorrowingIterator = BorrowingIteratorAdapter<Iterator>
2224

2325
/// An iterator over the members of a deque.
2426
struct Iterator: IteratorProtocol {

stdlib/public/RuntimeModule/Base64.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ public struct Base64Encoder<S: Sequence>: Sequence
217217
public struct Base64Decoder<S: Sequence>: Sequence
218218
where S.Element == UTF8.CodeUnit
219219
{
220+
@available(macOS 9999, *)
221+
public typealias BorrowingIterator = BorrowingIteratorAdapter<Iterator>
220222
public typealias Element = UInt8
221223

222224
var source: S

stdlib/public/RuntimeModule/Elf.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,6 +1266,8 @@ final class ElfImage<SomeElfTraits: ElfTraits>
12661266
}
12671267

12681268
struct Notes: Sequence {
1269+
typealias Element = Note
1270+
12691271
var image: ElfImage<Traits>
12701272

12711273
struct NoteIterator: IteratorProtocol {

stdlib/public/RuntimeModule/FramePointerUnwinder.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public struct FramePointerUnwinder<C: Context, M: MemoryReader>: Sequence, Itera
2121
public typealias Context = C
2222
public typealias MemoryReader = M
2323
public typealias Address = Context.Address
24+
public typealias Element = RichFrame<Address>
2425

2526
var pc: Address
2627
var fp: Address

stdlib/public/StringProcessing/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ set(swift_string_processing_compile_flags)
2020
# will be built with library evolution.
2121
list(APPEND swift_string_processing_compile_flags
2222
"-DRESILIENT_LIBRARIES")
23+
list(APPEND swift_string_processing_compile_flags "-Xfrontend" "-disable-availability-checking")
2324

2425
if(SWIFT_BUILD_STATIC_STDLIB)
2526
# Explicitly autolink swift_RegexParser because it's imported with @_implementationOnly

stdlib/public/core/BorrowIteratorProtocol.swift renamed to stdlib/public/core/BorrowingIteratorProtocol.swift

Lines changed: 89 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
@available(SwiftStdlib 6.3, *)
14-
public protocol BorrowIteratorProtocol<Element>: ~Copyable, ~Escapable {
14+
public protocol BorrowingIteratorProtocol<Element>: ~Copyable, ~Escapable {
1515
associatedtype Element: ~Copyable
1616

1717
// FIXME: This ought to be a core requirement, but `Ref` is not a thing yet.
@@ -90,7 +90,7 @@ public protocol BorrowIteratorProtocol<Element>: ~Copyable, ~Escapable {
9090
}
9191

9292
@available(SwiftStdlib 6.3, *)
93-
extension BorrowIteratorProtocol where Self: ~Copyable & ~Escapable {
93+
extension BorrowingIteratorProtocol where Self: ~Copyable & ~Escapable {
9494
@_alwaysEmitIntoClient
9595
@_lifetime(&self)
9696
@_lifetime(self: copy self)
@@ -101,7 +101,7 @@ extension BorrowIteratorProtocol where Self: ~Copyable & ~Escapable {
101101
}
102102

103103
@available(SwiftStdlib 6.3, *)
104-
extension BorrowIteratorProtocol where Self: ~Copyable & ~Escapable {
104+
extension BorrowingIteratorProtocol where Self: ~Copyable & ~Escapable {
105105
@_alwaysEmitIntoClient
106106
@_lifetime(self: copy self)
107107
public mutating func skip(by offset: Int) -> Int {
@@ -115,29 +115,29 @@ extension BorrowIteratorProtocol where Self: ~Copyable & ~Escapable {
115115
}
116116
}
117117

118-
@available(SwiftStdlib 6.3, *)
119-
extension Span: Iterable where Element: ~Copyable {
120-
// FIXME: This simple definition cannot also be a backward (or bidirectional)
121-
// iterator, nor a random-access iterator. If we want to go in that direction,
122-
// we'll need to rather introduce a type more like `RigidArray.BorrowIterator`.
123-
public typealias BorrowIterator = Self
124-
125-
@_alwaysEmitIntoClient
126-
@_transparent
127-
public var estimatedCount: EstimatedCount {
128-
.exactly(count)
129-
}
130-
131-
@_alwaysEmitIntoClient
132-
@_lifetime(copy self)
133-
@_transparent
134-
public func startBorrowIteration() -> Span<Element> {
135-
self
136-
}
137-
}
118+
//@available(SwiftStdlib 6.3, *)
119+
//extension Span: Iterable where Element: ~Copyable {
120+
// // FIXME: This simple definition cannot also be a backward (or bidirectional)
121+
// // iterator, nor a random-access iterator. If we want to go in that direction,
122+
// // we'll need to rather introduce a type more like `RigidArray.BorrowIterator`.
123+
// public typealias BorrowIterator = Self
124+
//
125+
// @_alwaysEmitIntoClient
126+
// @_transparent
127+
// public var estimatedCount: EstimatedCount {
128+
// .exactly(count)
129+
// }
130+
//
131+
// @_alwaysEmitIntoClient
132+
// @_lifetime(copy self)
133+
// @_transparent
134+
// public func startBorrowIteration() -> Span<Element> {
135+
// self
136+
// }
137+
//}
138138

139139
@available(SwiftStdlib 6.3, *)
140-
extension Span: BorrowIteratorProtocol where Element: ~Copyable {
140+
extension Span: BorrowingIteratorProtocol where Element: ~Copyable {
141141
@_alwaysEmitIntoClient
142142
@_lifetime(&self)
143143
@_lifetime(self: copy self)
@@ -149,37 +149,79 @@ extension Span: BorrowIteratorProtocol where Element: ~Copyable {
149149
}
150150

151151
@available(SwiftStdlib 6.3, *)
152-
extension MutableSpan: Iterable where Element: ~Copyable {
153-
public typealias BorrowIterator = Span<Element>.BorrowIterator
154-
155-
@_alwaysEmitIntoClient
156-
@_transparent
157-
public var estimatedCount: EstimatedCount {
158-
.exactly(count)
159-
}
160-
152+
extension Span: Sequence /* where Element: ~Copyable */ {
153+
public typealias Iterator = NeverIterator<Element>
154+
161155
@_alwaysEmitIntoClient
162156
@_lifetime(borrow self)
163-
@_transparent
164-
public func startBorrowIteration() -> Span<Element> {
165-
span
157+
public func makeBorrowingIterator() -> Span<Element> {
158+
self
166159
}
167160
}
168161

169-
@available(SwiftStdlib 6.3, *)
170-
extension OutputSpan: Iterable where Element: ~Copyable {
171-
public typealias BorrowIterator = Span<Element>.BorrowIterator
172-
173-
@_alwaysEmitIntoClient
174-
@_transparent
175-
public var estimatedCount: EstimatedCount {
176-
.exactly(count)
162+
extension InlineArray: Sequence /* where Element: ~Copyable */ {
163+
public typealias Element = Element
164+
// public typealias Iterator = NeverIterator<Element>
165+
public typealias BorrowingIterator = Span<Element>
166+
167+
// This will NOT work once `Element: ~Copyable` is in the works
168+
// Problematic because we can only conform to `Sequence` once, so we
169+
// need to provide a single iterator type, but it can't handle both
170+
// ~Copyable and copyable elements (I think)
171+
public struct Iterator: IteratorProtocol {
172+
var array: [count of Element]
173+
var index: Int = 0
174+
175+
public mutating func next() -> Element? {
176+
guard index < array.count else { return nil }
177+
defer { index &+= 1 }
178+
return array[index]
179+
}
177180
}
178-
181+
182+
public func makeIterator() -> Iterator {
183+
.init(array: self)
184+
}
185+
179186
@_alwaysEmitIntoClient
180187
@_lifetime(borrow self)
181-
@_transparent
182-
public func startBorrowIteration() -> Span<Element> {
188+
public func makeBorrowingIterator() -> Span<Element> {
183189
self.span
184190
}
185191
}
192+
193+
//@available(SwiftStdlib 6.3, *)
194+
//extension MutableSpan: Iterable where Element: ~Copyable {
195+
// public typealias BorrowIterator = Span<Element>.BorrowIterator
196+
//
197+
// @_alwaysEmitIntoClient
198+
// @_transparent
199+
// public var estimatedCount: EstimatedCount {
200+
// .exactly(count)
201+
// }
202+
//
203+
// @_alwaysEmitIntoClient
204+
// @_lifetime(borrow self)
205+
// @_transparent
206+
// public func startBorrowIteration() -> Span<Element> {
207+
// span
208+
// }
209+
//}
210+
//
211+
//@available(SwiftStdlib 6.3, *)
212+
//extension OutputSpan: Iterable where Element: ~Copyable {
213+
// public typealias BorrowIterator = Span<Element>.BorrowIterator
214+
//
215+
// @_alwaysEmitIntoClient
216+
// @_transparent
217+
// public var estimatedCount: EstimatedCount {
218+
// .exactly(count)
219+
// }
220+
//
221+
// @_alwaysEmitIntoClient
222+
// @_lifetime(borrow self)
223+
// @_transparent
224+
// public func startBorrowIteration() -> Span<Element> {
225+
// self.span
226+
// }
227+
//}

0 commit comments

Comments
 (0)