Skip to content

[stdlib] Simplify internal DropFirst/PrefixSequence types #19970

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
134 changes: 66 additions & 68 deletions stdlib/public/core/Sequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -646,52 +646,44 @@ extension Sequence where Self.Iterator == Self {
/// `Base` iterator before possibly returning the first available element.
///
/// The underlying iterator's sequence may be infinite.
@usableFromInline
@_fixed_layout
internal struct _DropFirstSequence<Base : IteratorProtocol>
: Sequence, IteratorProtocol {

@usableFromInline
internal struct DropFirstSequence<Base: Sequence> {
@usableFromInline
internal var _iterator: Base
internal let _base: Base
@usableFromInline
internal let _limit: Int
@usableFromInline
internal var _dropped: Int

@inlinable
internal init(_iterator: Base, limit: Int, dropped: Int = 0) {
self._iterator = _iterator
self._limit = limit
self._dropped = dropped
}

@inlinable
__consuming internal func makeIterator() -> _DropFirstSequence<Base> {
return self

@inlinable
public init(_ base: Base, dropping limit: Int) {
_precondition(limit >= 0,
"Can't drop a negative number of elements from a sequence")
_base = base
_limit = limit
}
}

extension DropFirstSequence: Sequence {
public typealias Element = Base.Element
public typealias Iterator = Base.Iterator
public typealias SubSequence = AnySequence<Element>

@inlinable
internal mutating func next() -> Base.Element? {
while _dropped < _limit {
if _iterator.next() == nil {
_dropped = _limit
return nil
}
_dropped += 1
}
return _iterator.next()
public __consuming func makeIterator() -> Iterator {
var it = _base.makeIterator()
var dropped = 0
while dropped < _limit, it.next() != nil { dropped &+= 1 }
return it
}

@inlinable
internal __consuming func dropFirst(_ k: Int) -> AnySequence<Base.Element> {
public __consuming func dropFirst(_ k: Int) -> AnySequence<Element> {
// If this is already a _DropFirstSequence, we need to fold in
// the current drop count and drop limit so no data is lost.
//
// i.e. [1,2,3,4].dropFirst(1).dropFirst(1) should be equivalent to
// [1,2,3,4].dropFirst(2).
return AnySequence(
_DropFirstSequence(
_iterator: _iterator, limit: _limit + k, dropped: _dropped))
return AnySequence(DropFirstSequence(_base, dropping: _limit + k))
}
}

Expand All @@ -701,47 +693,60 @@ internal struct _DropFirstSequence<Base : IteratorProtocol>
/// The underlying iterator's sequence may be infinite.
@_fixed_layout
@usableFromInline
internal struct _PrefixSequence<Base : IteratorProtocol>
: Sequence, IteratorProtocol {
@usableFromInline
internal let _maxLength: Int
internal struct PrefixSequence<Base: Sequence> {
@usableFromInline
internal var _iterator: Base
internal var _base: Base
@usableFromInline
internal var _taken: Int
internal let _maxLength: Int

@inlinable
internal init(_iterator: Base, maxLength: Int, taken: Int = 0) {
self._iterator = _iterator
self._maxLength = maxLength
self._taken = taken
public init(_ base: Base, maxLength: Int) {
_precondition(maxLength >= 0, "Can't take a prefix of negative length")
_base = base
_maxLength = maxLength
}
}

@inlinable
__consuming internal func makeIterator() -> _PrefixSequence<Base> {
return self
}
extension PrefixSequence {
@_fixed_layout
public struct Iterator {
@usableFromInline
internal var _base: Base.Iterator
@usableFromInline
internal var _remaining: Int

@inlinable
internal init(_ base: Base.Iterator, maxLength: Int) {
_base = base
_remaining = maxLength
}
}
}

extension PrefixSequence.Iterator: IteratorProtocol {
public typealias Element = Base.Element

@inlinable
internal mutating func next() -> Base.Element? {
if _taken >= _maxLength { return nil }
_taken += 1

if let next = _iterator.next() {
return next
internal mutating func next() -> Element? {
if _remaining != 0 {
_remaining &-= 1
return _base.next()
} else {
return nil
}
}
}

_taken = _maxLength
return nil
extension PrefixSequence: Sequence {
@inlinable
public __consuming func makeIterator() -> Iterator {
return Iterator(_base.makeIterator(), maxLength: _maxLength)
}

@inlinable
internal __consuming func prefix(_ maxLength: Int) -> AnySequence<Base.Element> {
return AnySequence(
_PrefixSequence(
_iterator: _iterator,
maxLength: Swift.min(maxLength, self._maxLength),
taken: _taken))
public __consuming func prefix(_ maxLength: Int) -> AnySequence<Element> {
let length = Swift.min(maxLength, self._maxLength)
return AnySequence(PrefixSequence(_base, maxLength: length))
}
}

Expand Down Expand Up @@ -1223,9 +1228,7 @@ extension Sequence where SubSequence == AnySequence<Element> {
/// the sequence.
@inlinable
public __consuming func dropFirst(_ k: Int) -> AnySequence<Element> {
_precondition(k >= 0, "Can't drop a negative number of elements from a sequence")
if k == 0 { return AnySequence(self) }
return AnySequence(_DropFirstSequence(_iterator: makeIterator(), limit: k))
return AnySequence(DropFirstSequence(self, dropping: k))
}

/// Returns a subsequence containing all but the given number of final
Expand Down Expand Up @@ -1325,12 +1328,7 @@ extension Sequence where SubSequence == AnySequence<Element> {
/// - Complexity: O(1)
@inlinable
public __consuming func prefix(_ maxLength: Int) -> AnySequence<Element> {
_precondition(maxLength >= 0, "Can't take a prefix of negative length from a sequence")
if maxLength == 0 {
return AnySequence(EmptyCollection<Element>())
}
return AnySequence(
_PrefixSequence(_iterator: makeIterator(), maxLength: maxLength))
return AnySequence(PrefixSequence(self, maxLength: maxLength))
}

/// Returns a subsequence containing the initial, consecutive elements that
Expand Down
23 changes: 23 additions & 0 deletions test/api-digester/Outputs/stability-stdlib-abi.swift.expected
Original file line number Diff line number Diff line change
@@ -1,16 +1,39 @@

/* Generic Signature Changes */
Func _DropFirstSequence.dropFirst(_:) has generic signature change from <τ_0_0 where τ_0_0 : IteratorProtocol> to <τ_0_0 where τ_0_0 : Sequence>
Func _DropFirstSequence.makeIterator() has generic signature change from <τ_0_0 where τ_0_0 : IteratorProtocol> to <τ_0_0 where τ_0_0 : Sequence>
Func _PrefixSequence.makeIterator() has generic signature change from <τ_0_0 where τ_0_0 : IteratorProtocol> to <τ_0_0 where τ_0_0 : Sequence>
Func _PrefixSequence.prefix(_:) has generic signature change from <τ_0_0 where τ_0_0 : IteratorProtocol> to <τ_0_0 where τ_0_0 : Sequence>
Struct _DropFirstSequence has generic signature change from <τ_0_0 where τ_0_0 : IteratorProtocol> to <τ_0_0 where τ_0_0 : Sequence>
Struct _PrefixSequence has generic signature change from <τ_0_0 where τ_0_0 : IteratorProtocol> to <τ_0_0 where τ_0_0 : Sequence>

/* RawRepresentable Changes */

/* Removed Decls */
Constructor _DropFirstSequence.init(_iterator:limit:dropped:) has been removed
Constructor _PrefixSequence.init(_iterator:maxLength:taken:) has been removed
Func _DropFirstSequence.next() has been removed
Func _PrefixSequence.next() has been removed
Var _DropFirstSequence._dropped has been removed
Var _DropFirstSequence._iterator has been removed
Var _PrefixSequence._iterator has been removed
Var _PrefixSequence._taken has been removed

/* Moved Decls */
Struct _DropFirstSequence has been renamed to Struct DropFirstSequence
Struct _PrefixSequence has been renamed to Struct PrefixSequence

/* Renamed Decls */

/* Type Changes */
Func _DropFirstSequence.makeIterator() has return type change from _DropFirstSequence<τ_0_0> to τ_0_0.Iterator
Func _PrefixSequence.makeIterator() has return type change from _PrefixSequence<τ_0_0> to PrefixSequence<τ_0_0>.Iterator
Var DropFirstSequence._base is added to a non-resilient type
Var PrefixSequence._base is added to a non-resilient type
Var _PrefixSequence._maxLength in a non-resilient type changes position from 0 to 1

/* Decl Attribute changes */

/* Protocol Requirement Changes */
Struct _DropFirstSequence has removed conformance to IteratorProtocol
Struct _PrefixSequence has removed conformance to IteratorProtocol