Skip to content

[stdlib] Change post-nil guarantee for IteratorProtocol.next() #1702

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions stdlib/public/core/Algorithm.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ public struct EnumeratedIterator<
/// The type of element returned by `next()`.
public typealias Element = (offset: Int, element: Base.Element)

/// Advance to the next element and return it, or `nil` if no next
/// element exists.
/// Advances to the next element and returns it, or `nil` if no next element
/// exists.
///
/// - Requires: No preceding call to `self.next()` has returned `nil`.
/// Once `nil` has been returned, all subsequent calls return `nil`.
public mutating func next() -> Element? {
guard let b = _base.next() else { return nil }
defer { _count += 1 }
Expand Down
6 changes: 2 additions & 4 deletions stdlib/public/core/Collection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -378,10 +378,8 @@ public struct IndexingIterator<
/// exists.
///
/// Repeatedly calling this method returns all the elements of the underlying
/// sequence in order. As soon as the sequence has run out of elements, the
/// `next()` method returns `nil`.
///
/// You must not call this method if it has previously returned `nil`.
/// sequence in order. As soon as the sequence has run out of elements, all
/// subsequent calls return `nil`.
///
/// This example shows how an iterator can be used explicitly to emulate a
/// `for`-`in` loop. First, retrieve a sequence's iterator, and then call
Expand Down
9 changes: 5 additions & 4 deletions stdlib/public/core/CollectionOfOne.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ public struct IteratorOverOne<Element> : IteratorProtocol, Sequence {
self._elements = _elements
}

/// Advance to the next element and return it, or `nil` if no next
/// element exists.
/// Advances to the next element and returns it, or `nil` if no next element
/// exists.
///
/// Once `nil` has been returned, all subsequent calls return `nil`.
///
/// - Precondition: `next()` has not been applied to a copy of `self`
/// since the copy was made, and no preceding call to `self.next()`
/// has returned `nil`.
/// since the copy was made.
public mutating func next() -> Element? {
let result = _elements
_elements = nil
Expand Down
12 changes: 8 additions & 4 deletions stdlib/public/core/ExistentialCollection.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,10 @@ public struct AnyIterator<Element> : IteratorProtocol {
self._box = _box
}

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

internal class _AnyIteratorBoxBase<Element> : IteratorProtocol {
/// Advances to the next element and returns it, or `nil` if no next
/// element exists.
/// Advances to the next element and returns it, or `nil` if no next element
/// exists.
///
/// Once `nil` has been returned, all subsequent calls return `nil`.
///
/// - Note: Subclasses must override this method.
internal func next() -> Element? { _abstract() }
Expand Down
9 changes: 5 additions & 4 deletions stdlib/public/core/Filter.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ from gyb_stdlib_support import (
public struct LazyFilterIterator<
Base : IteratorProtocol
> : IteratorProtocol, Sequence {
/// Advances to the next element and returns it, or `nil` if no next
/// element exists.
/// Advances to the next element and returns it, or `nil` if no next element
/// exists.
///
/// Once `nil` has been returned, all subsequent calls return `nil`.
///
/// - Precondition: `next()` has not been applied to a copy of `self`
/// since the copy was made, and no preceding call to `self.next()`
/// has returned `nil`.
/// since the copy was made.
public mutating func next() -> Base.Element? {
while let n = _base.next() {
if _predicate(n) {
Expand Down
9 changes: 5 additions & 4 deletions stdlib/public/core/Flatten.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,13 @@ public struct FlattenIterator<
self._base = _base
}

/// Advance to the next element and return it, or `nil` if no next
/// element exists.
/// Advances to the next element and returns it, or `nil` if no next element
/// exists.
///
/// Once `nil` has been returned, all subsequent calls return `nil`.
///
/// - Precondition: `next()` has not been applied to a copy of `self`
/// since the copy was made, and no preceding call to `self.next()`
/// has returned `nil`.
/// since the copy was made.
public mutating func next() -> Base.Element.Iterator.Element? {
repeat {
if _fastPath(_inner != nil) {
Expand Down
6 changes: 3 additions & 3 deletions stdlib/public/core/HashedCollections.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -4860,10 +4860,10 @@ public struct ${Self}Iterator<${TypeParametersDecl}> : IteratorProtocol {
}
}

/// Advance to the next element and return it, or `nil` if no next
/// element exists.
/// Advances to the next element and returns it, or `nil` if no next element
/// exists.
///
/// - Precondition: No preceding call to `self.next()` has returned `nil`.
/// Once `nil` has been returned, all subsequent calls return `nil`.
@inline(__always)
public mutating func next() -> ${Sequence}? {
if _fastPath(_guaranteedNative) {
Expand Down
6 changes: 4 additions & 2 deletions stdlib/public/core/Join.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ public struct JoinedIterator<
self._separatorData = ContiguousArray(separator)
}

/// Advance to the next element and return it, or `nil` if no next
/// element exists.
/// Advances to the next element and returns it, or `nil` if no next element
/// exists.
///
/// Once `nil` has been returned, all subsequent calls return `nil`.
public mutating func next() -> Base.Element.Iterator.Element? {
repeat {
switch _state {
Expand Down
9 changes: 5 additions & 4 deletions stdlib/public/core/Map.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ from gyb_stdlib_support import (
public struct LazyMapIterator<
Base : IteratorProtocol, Element
> : IteratorProtocol, Sequence {
/// Advance to the next element and return it, or `nil` if no next
/// element exists.
/// Advances to the next element and returns it, or `nil` if no next element
/// exists.
///
/// Once `nil` has been returned, all subsequent calls return `nil`.
///
/// - Precondition: `next()` has not been applied to a copy of `self`
/// since the copy was made, and no preceding call to `self.next()`
/// has returned `nil`.
/// since the copy was made.
public mutating func next() -> Element? {
return _base.next().map(_transform)
}
Expand Down
22 changes: 11 additions & 11 deletions stdlib/public/core/Sequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -178,16 +178,15 @@ public protocol IteratorProtocol {
/// The type of element traversed by the iterator.
associatedtype Element

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

/// Advances to the next element and returns it, or `nil` if no next
/// element exists.
/// Advances to the next element and returns it, or `nil` if no next element
/// exists.
///
/// Once `nil` has been returned, all subsequent calls return `nil`.
///
/// - Precondition: `next()` has not been applied to a copy of `self`
/// since the copy was made, and no preceding call to `self.next()`
/// has returned `nil`.
/// since the copy was made.
public mutating func next() -> Base.Element? {
return _base.next()
}
Expand Down
12 changes: 8 additions & 4 deletions stdlib/public/core/Stride.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,10 @@ public struct StrideToIterator<Element : Strideable> : IteratorProtocol {
internal let _end: Element
internal let _stride: Element.Stride

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

/// Advance to the next element and return it, or `nil` if no next
/// element exists.
/// Advances to the next element and returns it, or `nil` if no next element
/// exists.
///
/// Once `nil` has been returned, all subsequent calls return `nil`.
public mutating func next() -> Element? {
if _done {
return nil
Expand Down
10 changes: 5 additions & 5 deletions stdlib/public/core/StringUnicodeScalarView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -245,13 +245,13 @@ extension String {
}
}

/// Advances to the next element and returns it.
/// Advances to the next element and returns it, or `nil` if no next
/// element exists.
///
/// Do not call this method if a copy of the iterator has been advanced.
/// Once `nil` has been returned, all subsequent calls return `nil`.
///
/// - Returns: The next element in the collection if an element is
/// available; otherwise, `nil`. After returning `nil` once, this
/// method returns `nil` on every subsequent call.
/// - Precondition: `next()` has not been applied to a copy of `self`
/// since the copy was made.
public mutating func next() -> UnicodeScalar? {
var result: UnicodeDecodingResult
if _baseSet {
Expand Down
6 changes: 4 additions & 2 deletions stdlib/public/core/UnsafeBufferPointer.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
public struct UnsafeBufferPointerIterator<Element>
: IteratorProtocol, Sequence {

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

Expand Down
9 changes: 5 additions & 4 deletions stdlib/public/core/Zip.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ public struct Zip2Iterator<
(_baseStream1, _baseStream2) = (iterator1, iterator2)
}

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