Skip to content

Commit 4614adc

Browse files
committed
Merge pull request #1702 from PatrickPijnappel/iterator-post-nil-guarantee
[stdlib] Change post-nil guarantee for IteratorProtocol.next()
2 parents 34aae89 + daec2da commit 4614adc

14 files changed

+73
-58
lines changed

stdlib/public/core/Algorithm.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ public struct EnumeratedIterator<
8080
/// The type of element returned by `next()`.
8181
public typealias Element = (offset: Int, element: Base.Element)
8282

83-
/// Advance to the next element and return it, or `nil` if no next
84-
/// element exists.
83+
/// Advances to the next element and returns it, or `nil` if no next element
84+
/// exists.
8585
///
86-
/// - Requires: No preceding call to `self.next()` has returned `nil`.
86+
/// Once `nil` has been returned, all subsequent calls return `nil`.
8787
public mutating func next() -> Element? {
8888
guard let b = _base.next() else { return nil }
8989
defer { _count += 1 }

stdlib/public/core/Collection.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -378,10 +378,8 @@ public struct IndexingIterator<
378378
/// exists.
379379
///
380380
/// Repeatedly calling this method returns all the elements of the underlying
381-
/// sequence in order. As soon as the sequence has run out of elements, the
382-
/// `next()` method returns `nil`.
383-
///
384-
/// You must not call this method if it has previously returned `nil`.
381+
/// sequence in order. As soon as the sequence has run out of elements, all
382+
/// subsequent calls return `nil`.
385383
///
386384
/// This example shows how an iterator can be used explicitly to emulate a
387385
/// `for`-`in` loop. First, retrieve a sequence's iterator, and then call

stdlib/public/core/CollectionOfOne.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ public struct IteratorOverOne<Element> : IteratorProtocol, Sequence {
1919
self._elements = _elements
2020
}
2121

22-
/// Advance to the next element and return it, or `nil` if no next
23-
/// element exists.
22+
/// Advances to the next element and returns it, or `nil` if no next element
23+
/// exists.
24+
///
25+
/// Once `nil` has been returned, all subsequent calls return `nil`.
2426
///
2527
/// - Precondition: `next()` has not been applied to a copy of `self`
26-
/// since the copy was made, and no preceding call to `self.next()`
27-
/// has returned `nil`.
28+
/// since the copy was made.
2829
public mutating func next() -> Element? {
2930
let result = _elements
3031
_elements = nil

stdlib/public/core/ExistentialCollection.swift.gyb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,10 @@ public struct AnyIterator<Element> : IteratorProtocol {
7474
self._box = _box
7575
}
7676

77-
/// Advances to the next element and returns it, or `nil` if no next
78-
/// element exists.
77+
/// Advances to the next element and returns it, or `nil` if no next element
78+
/// exists.
79+
///
80+
/// Once `nil` has been returned, all subsequent calls return `nil`.
7981
public func next() -> Element? {
8082
return _box.next()
8183
}
@@ -96,8 +98,10 @@ internal struct _ClosureBasedIterator<Element> : IteratorProtocol {
9698
}
9799

98100
internal class _AnyIteratorBoxBase<Element> : IteratorProtocol {
99-
/// Advances to the next element and returns it, or `nil` if no next
100-
/// element exists.
101+
/// Advances to the next element and returns it, or `nil` if no next element
102+
/// exists.
103+
///
104+
/// Once `nil` has been returned, all subsequent calls return `nil`.
101105
///
102106
/// - Note: Subclasses must override this method.
103107
internal func next() -> Element? { _abstract() }

stdlib/public/core/Filter.swift.gyb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@ from gyb_stdlib_support import (
2626
public struct LazyFilterIterator<
2727
Base : IteratorProtocol
2828
> : IteratorProtocol, Sequence {
29-
/// Advances to the next element and returns it, or `nil` if no next
30-
/// element exists.
29+
/// Advances to the next element and returns it, or `nil` if no next element
30+
/// exists.
31+
///
32+
/// Once `nil` has been returned, all subsequent calls return `nil`.
3133
///
3234
/// - Precondition: `next()` has not been applied to a copy of `self`
33-
/// since the copy was made, and no preceding call to `self.next()`
34-
/// has returned `nil`.
35+
/// since the copy was made.
3536
public mutating func next() -> Base.Element? {
3637
while let n = _base.next() {
3738
if _predicate(n) {

stdlib/public/core/Flatten.swift.gyb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,13 @@ public struct FlattenIterator<
3535
self._base = _base
3636
}
3737

38-
/// Advance to the next element and return it, or `nil` if no next
39-
/// element exists.
38+
/// Advances to the next element and returns it, or `nil` if no next element
39+
/// exists.
40+
///
41+
/// Once `nil` has been returned, all subsequent calls return `nil`.
4042
///
4143
/// - Precondition: `next()` has not been applied to a copy of `self`
42-
/// since the copy was made, and no preceding call to `self.next()`
43-
/// has returned `nil`.
44+
/// since the copy was made.
4445
public mutating func next() -> Base.Element.Iterator.Element? {
4546
repeat {
4647
if _fastPath(_inner != nil) {

stdlib/public/core/HashedCollections.swift.gyb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4860,10 +4860,10 @@ public struct ${Self}Iterator<${TypeParametersDecl}> : IteratorProtocol {
48604860
}
48614861
}
48624862

4863-
/// Advance to the next element and return it, or `nil` if no next
4864-
/// element exists.
4863+
/// Advances to the next element and returns it, or `nil` if no next element
4864+
/// exists.
48654865
///
4866-
/// - Precondition: No preceding call to `self.next()` has returned `nil`.
4866+
/// Once `nil` has been returned, all subsequent calls return `nil`.
48674867
@inline(__always)
48684868
public mutating func next() -> ${Sequence}? {
48694869
if _fastPath(_guaranteedNative) {

stdlib/public/core/Join.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@ public struct JoinedIterator<
3636
self._separatorData = ContiguousArray(separator)
3737
}
3838

39-
/// Advance to the next element and return it, or `nil` if no next
40-
/// element exists.
39+
/// Advances to the next element and returns it, or `nil` if no next element
40+
/// exists.
41+
///
42+
/// Once `nil` has been returned, all subsequent calls return `nil`.
4143
public mutating func next() -> Base.Element.Iterator.Element? {
4244
repeat {
4345
switch _state {

stdlib/public/core/Map.swift.gyb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ from gyb_stdlib_support import (
2424
public struct LazyMapIterator<
2525
Base : IteratorProtocol, Element
2626
> : IteratorProtocol, Sequence {
27-
/// Advance to the next element and return it, or `nil` if no next
28-
/// element exists.
27+
/// Advances to the next element and returns it, or `nil` if no next element
28+
/// exists.
29+
///
30+
/// Once `nil` has been returned, all subsequent calls return `nil`.
2931
///
3032
/// - Precondition: `next()` has not been applied to a copy of `self`
31-
/// since the copy was made, and no preceding call to `self.next()`
32-
/// has returned `nil`.
33+
/// since the copy was made.
3334
public mutating func next() -> Element? {
3435
return _base.next().map(_transform)
3536
}

stdlib/public/core/Sequence.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -178,16 +178,15 @@ public protocol IteratorProtocol {
178178
/// The type of element traversed by the iterator.
179179
associatedtype Element
180180

181-
/// Advances and returns the next element of the underlying sequence, or
182-
/// `nil` if no next element exists.
181+
/// Advances to the next element and returns it, or `nil` if no next element
182+
/// exists. Once `nil` has been returned, all subsequent calls return `nil`.
183183
///
184184
/// Repeatedly calling this method returns, in order, all the elements of the
185-
/// underlying sequence. After the sequence has run out of elements, the
186-
/// `next()` method returns `nil`.
185+
/// underlying sequence. As soon as the sequence has run out of elements, all
186+
/// subsequent calls return `nil`.
187187
///
188-
/// You must not call this method if it has previously returned `nil` or if
189-
/// any other copy of this iterator has been advanced with a call to its
190-
/// `next()` method.
188+
/// You must not call this method if any other copy of this iterator has been
189+
/// advanced with a call to its `next()` method.
191190
///
192191
/// The following example shows how an iterator can be used explicitly to
193192
/// emulate a `for`-`in` loop. First, retrieve a sequence's iterator, and
@@ -1196,12 +1195,13 @@ public struct IteratorSequence<
11961195
_base = base
11971196
}
11981197

1199-
/// Advances to the next element and returns it, or `nil` if no next
1200-
/// element exists.
1198+
/// Advances to the next element and returns it, or `nil` if no next element
1199+
/// exists.
1200+
///
1201+
/// Once `nil` has been returned, all subsequent calls return `nil`.
12011202
///
12021203
/// - Precondition: `next()` has not been applied to a copy of `self`
1203-
/// since the copy was made, and no preceding call to `self.next()`
1204-
/// has returned `nil`.
1204+
/// since the copy was made.
12051205
public mutating func next() -> Base.Element? {
12061206
return _base.next()
12071207
}

stdlib/public/core/Stride.swift.gyb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,10 @@ public struct StrideToIterator<Element : Strideable> : IteratorProtocol {
131131
internal let _end: Element
132132
internal let _stride: Element.Stride
133133

134-
/// Advance to the next element and return it, or `nil` if no next
135-
/// element exists.
134+
/// Advances to the next element and returns it, or `nil` if no next element
135+
/// exists.
136+
///
137+
/// Once `nil` has been returned, all subsequent calls return `nil`.
136138
public mutating func next() -> Element? {
137139
if _stride > 0 ? _current >= _end : _current <= _end {
138140
return nil
@@ -188,8 +190,10 @@ public struct StrideThroughIterator<Element : Strideable> : IteratorProtocol {
188190
internal let _stride: Element.Stride
189191
internal var _done: Bool = false
190192

191-
/// Advance to the next element and return it, or `nil` if no next
192-
/// element exists.
193+
/// Advances to the next element and returns it, or `nil` if no next element
194+
/// exists.
195+
///
196+
/// Once `nil` has been returned, all subsequent calls return `nil`.
193197
public mutating func next() -> Element? {
194198
if _done {
195199
return nil

stdlib/public/core/StringUnicodeScalarView.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -245,13 +245,13 @@ extension String {
245245
}
246246
}
247247

248-
/// Advances to the next element and returns it.
248+
/// Advances to the next element and returns it, or `nil` if no next
249+
/// element exists.
249250
///
250-
/// Do not call this method if a copy of the iterator has been advanced.
251+
/// Once `nil` has been returned, all subsequent calls return `nil`.
251252
///
252-
/// - Returns: The next element in the collection if an element is
253-
/// available; otherwise, `nil`. After returning `nil` once, this
254-
/// method returns `nil` on every subsequent call.
253+
/// - Precondition: `next()` has not been applied to a copy of `self`
254+
/// since the copy was made.
255255
public mutating func next() -> UnicodeScalar? {
256256
var result: UnicodeDecodingResult
257257
if _baseSet {

stdlib/public/core/UnsafeBufferPointer.swift.gyb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
public struct UnsafeBufferPointerIterator<Element>
1616
: IteratorProtocol, Sequence {
1717

18-
/// Advance to the next element and return it, or `nil` if no next
19-
/// element exists.
18+
/// Advances to the next element and returns it, or `nil` if no next element
19+
/// exists.
20+
///
21+
/// Once `nil` has been returned, all subsequent calls return `nil`.
2022
public mutating func next() -> Element? {
2123
if _position == _end { return nil }
2224

stdlib/public/core/Zip.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,13 @@ public struct Zip2Iterator<
3131
(_baseStream1, _baseStream2) = (iterator1, iterator2)
3232
}
3333

34-
/// Advance to the next element and return it, or `nil` if no next
35-
/// element exists.
34+
/// Advances to the next element and returns it, or `nil` if no next element
35+
/// exists.
36+
///
37+
/// Once `nil` has been returned, all subsequent calls return `nil`.
3638
///
3739
/// - Precondition: `next()` has not been applied to a copy of `self`
38-
/// since the copy was made, and no preceding call to `self.next()`
39-
/// has returned `nil`.
40+
/// since the copy was made.
4041
public mutating func next() -> Element? {
4142
// The next() function needs to track if it has reached the end. If we
4243
// didn't, and the first sequence is longer than the second, then when we

0 commit comments

Comments
 (0)