Skip to content

Commit 020841d

Browse files
[stdlib] Add post-nil guarantee for IteratorProtocol.next() to always return nil
1 parent 149fd43 commit 020841d

14 files changed

+40
-57
lines changed

stdlib/public/core/Algorithm.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,8 @@ public struct EnumeratedIterator<
8484
/// The type of element returned by `next()`.
8585
public typealias Element = (offset: Int, element: Base.Element)
8686

87-
/// Advance to the next element and return it, or `nil` if no next
88-
/// element exists.
89-
///
90-
/// - Requires: No preceding call to `self.next()` has returned `nil`.
87+
/// Advance to the next element and return it, or `nil` if no next element
88+
/// exists. Once `nil` has been returned, all subsequent calls return `nil`.
9189
public mutating func next() -> Element? {
9290
guard let b = _base.next() else { return nil }
9391
defer { _count += 1 }

stdlib/public/core/Collection.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,8 @@ public struct IndexingIterator<Elements : Indexable>
8181
self._position = _elements.startIndex
8282
}
8383

84-
/// Advance to the next element and return it, or `nil` if no next
85-
/// element exists.
86-
///
87-
/// - Precondition: No preceding call to `self.next()` has returned `nil`.
84+
/// Advance to the next element and return it, or `nil` if no next element
85+
/// exists. Once `nil` has been returned, all subsequent calls return `nil`.
8886
public mutating func next() -> Elements._Element? {
8987
if _position == _elements.endIndex { return nil }
9088
let element = _elements[_position]

stdlib/public/core/CollectionOfOne.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@ 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+
/// Advance to the next element and return it, or `nil` if no next element
23+
/// exists. Once `nil` has been returned, all subsequent calls return `nil`.
2424
///
2525
/// - 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`.
26+
/// since the copy was made.
2827
public mutating func next() -> Element? {
2928
let result = _elements
3029
_elements = nil

stdlib/public/core/ExistentialCollection.swift.gyb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ public struct AnyIterator<Element> : IteratorProtocol {
6666
self._box = _box
6767
}
6868

69-
/// Advance to the next element and return it, or `nil` if no next
70-
/// element exists.
69+
/// Advance to the next element and return it, or `nil` if no next element
70+
/// exists. Once `nil` has been returned, all subsequent calls return `nil`.
7171
public func next() -> Element? {
7272
return _box.next()
7373
}
@@ -92,8 +92,8 @@ internal class _AnyIteratorBase {}
9292
internal class _AnyIteratorBoxBase<Element>
9393
: _AnyIteratorBase, IteratorProtocol {
9494

95-
/// Advance to the next element and return it, or `nil` if no next
96-
/// element exists.
95+
/// Advance to the next element and return it, or `nil` if no next element
96+
/// exists. Once `nil` has been returned, all subsequent calls return `nil`.
9797
///
9898
/// - Note: Subclasses must override this method.
9999
internal func next() -> Element? { _abstract() }

stdlib/public/core/Flatten.swift.gyb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,11 @@ public struct FlattenIterator<
2727
self._base = base
2828
}
2929

30-
/// Advance to the next element and return it, or `nil` if no next
31-
/// element exists.
30+
/// Advance to the next element and return it, or `nil` if no next element
31+
/// exists. Once `nil` has been returned, all subsequent calls return `nil`.
3232
///
3333
/// - Precondition: `next()` has not been applied to a copy of `self`
34-
/// since the copy was made, and no preceding call to `self.next()`
35-
/// has returned `nil`.
34+
/// since the copy was made.
3635
public mutating func next() -> Base.Element.Iterator.Element? {
3736
repeat {
3837
if _fastPath(_inner != nil) {

stdlib/public/core/HashedCollections.swift.gyb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3983,10 +3983,8 @@ public struct ${Self}Iterator<${TypeParametersDecl}> : IteratorProtocol {
39833983
}
39843984
}
39853985

3986-
/// Advance to the next element and return it, or `nil` if no next
3987-
/// element exists.
3988-
///
3989-
/// - Precondition: No preceding call to `self.next()` has returned `nil`.
3986+
/// Advance to the next element and return it, or `nil` if no next element
3987+
/// exists. Once `nil` has been returned, all subsequent calls return `nil`.
39903988
public mutating func next() -> ${Sequence}? {
39913989
if _fastPath(_guaranteedNative) {
39923990
return _nativeNext()

stdlib/public/core/Join.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ 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+
/// Advance to the next element and return it, or `nil` if no next element
40+
/// exists. Once `nil` has been returned, all subsequent calls return `nil`.
4141
public mutating func next() -> Base.Element.Iterator.Element? {
4242
repeat {
4343
switch _state {

stdlib/public/core/Map.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616
public struct LazyMapIterator<
1717
Base : IteratorProtocol, Element
1818
> : IteratorProtocol, Sequence {
19-
/// Advance to the next element and return it, or `nil` if no next
20-
/// element exists.
19+
/// Advance to the next element and return it, or `nil` if no next element
20+
/// exists. Once `nil` has been returned, all subsequent calls return `nil`.
2121
///
2222
/// - Precondition: `next()` has not been applied to a copy of `self`
23-
/// since the copy was made, and no preceding call to `self.next()`
24-
/// has returned `nil`.
23+
/// since the copy was made.
2524
public mutating func next() -> Element? {
2625
return _base.next().map(_transform)
2726
}

stdlib/public/core/Range.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ public struct RangeIterator<
2222
self.endIndex = _bounds.endIndex
2323
}
2424

25-
/// Advance to the next element and return it, or `nil` if no next
26-
/// element exists.
25+
/// Advance to the next element and return it, or `nil` if no next element
26+
/// exists. Once `nil` has been returned, all subsequent calls return `nil`.
2727
public mutating func next() -> Element? {
2828
if startIndex == endIndex { return nil }
2929
let element = startIndex

stdlib/public/core/Sequence.swift

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,11 @@ public protocol IteratorProtocol {
2626
/// The type of element traversed by `self`.
2727
associatedtype Element
2828

29-
/// Advance to the next element and return it, or `nil` if no next
30-
/// element exists.
29+
/// Advance to the next element and return it, or `nil` if no next element
30+
/// exists. Once `nil` has been returned, all subsequent calls return `nil`.
3131
///
3232
/// - 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`. Specific implementations of this protocol
35-
/// are encouraged to respond to violations of this requirement by
36-
/// calling `preconditionFailure("...")`.
33+
/// since the copy was made.
3734
@warn_unused_result
3835
mutating func next() -> Element?
3936
}
@@ -637,12 +634,11 @@ public struct IteratorSequence<
637634
_base = base
638635
}
639636

640-
/// Advance to the next element and return it, or `nil` if no next
641-
/// element exists.
637+
/// Advance to the next element and return it, or `nil` if no next element
638+
/// exists. Once `nil` has been returned, all subsequent calls return `nil`.
642639
///
643640
/// - Precondition: `next()` has not been applied to a copy of `self`
644-
/// since the copy was made, and no preceding call to `self.next()`
645-
/// has returned `nil`.
641+
/// since the copy was made.
646642
public mutating func next() -> Base.Element? {
647643
return _base.next()
648644
}

0 commit comments

Comments
 (0)