Skip to content

Commit f2f103d

Browse files
author
Max Moiseev
committed
Rearrange code in LazyFilterCollection and provide delegating overrides
(cherry picked from commit 1388064)
1 parent 1c75bd2 commit f2f103d

File tree

1 file changed

+118
-41
lines changed

1 file changed

+118
-41
lines changed

stdlib/public/core/Filter.swift

Lines changed: 118 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -126,17 +126,11 @@ public typealias LazyFilterIndex<Base : Collection> = Base.Index
126126
/// general operations on `LazyFilterCollection` instances may not have the
127127
/// documented complexity.
128128
@_fixed_layout // FIXME(sil-serialize-all)
129-
public struct LazyFilterCollection<
130-
Base : Collection
131-
> : LazyCollectionProtocol, Collection {
132-
133-
/// A type that represents a valid position in the collection.
134-
///
135-
/// Valid indices consist of the position of every element and a
136-
/// "past the end" position that's not valid for use as a subscript.
137-
public typealias Index = Base.Index
138-
public typealias Element = Base.Element
139-
129+
public struct LazyFilterCollection<Base : Collection> {
130+
@_versioned // FIXME(sil-serialize-all)
131+
internal var _base: Base
132+
@_versioned // FIXME(sil-serialize-all)
133+
internal let _predicate: (Base.Element) -> Bool
140134

141135
/// Creates an instance containing the elements of `base` that
142136
/// satisfy `isIncluded`.
@@ -149,6 +143,38 @@ public struct LazyFilterCollection<
149143
self._base = _base
150144
self._predicate = isIncluded
151145
}
146+
}
147+
148+
extension LazyFilterCollection : Sequence {
149+
public typealias SubSequence = LazyFilterCollection<Base.SubSequence>
150+
public typealias Element = Base.Element
151+
152+
// Any estimate of the number of elements that pass `_predicate` requires
153+
// iterating the collection and evaluating each element, which can be costly,
154+
// is unexpected, and usually doesn't pay for itself in saving time through
155+
// preventing intermediate reallocations. (SR-4164)
156+
@_inlineable // FIXME(sil-serialize-all)
157+
public var underestimatedCount: Int { return 0 }
158+
159+
@_inlineable // FIXME(sil-serialize-all)
160+
public func _copyToContiguousArray()
161+
-> ContiguousArray<Base.Iterator.Element> {
162+
163+
// The default implementation of `_copyToContiguousArray` queries the
164+
// `count` property, which evaluates `_predicate` for every element --
165+
// see the note above `underestimatedCount`. Here we treat `self` as a
166+
// sequence and only rely on underestimated count.
167+
return _copySequenceToContiguousArray(self)
168+
}
169+
170+
/// Returns an iterator over the elements of this sequence.
171+
///
172+
/// - Complexity: O(1).
173+
@_inlineable // FIXME(sil-serialize-all)
174+
public func makeIterator() -> LazyFilterIterator<Base.Iterator> {
175+
return LazyFilterIterator(
176+
_base: _base.makeIterator(), _predicate)
177+
}
152178

153179
@_inlineable
154180
public func _customContainsEquatableElement(
@@ -162,6 +188,14 @@ public struct LazyFilterCollection<
162188
}
163189
return nil
164190
}
191+
}
192+
193+
extension LazyFilterCollection : LazyCollectionProtocol, Collection {
194+
/// A type that represents a valid position in the collection.
195+
///
196+
/// Valid indices consist of the position of every element and a
197+
/// "past the end" position that's not valid for use as a subscript.
198+
public typealias Index = Base.Index
165199

166200
/// The position of the first element in a non-empty collection.
167201
///
@@ -207,53 +241,96 @@ public struct LazyFilterCollection<
207241
i = index
208242
}
209243

210-
/// Accesses the element at `position`.
211-
///
212-
/// - Precondition: `position` is a valid position in `self` and
213-
/// `position != endIndex`.
214244
@_inlineable // FIXME(sil-serialize-all)
215-
public subscript(position: Index) -> Base.Element {
216-
return _base[position]
245+
// FIXME(conditional-conformances): this is a copy of a default
246+
// implementation. Can be removed once teh default one allows negative
247+
// results to be returned.
248+
public func distance(from start: Index, to end: Index) -> Int {
249+
var _start: Index
250+
let _end: Index
251+
let step: Int
252+
if start > end {
253+
_start = end
254+
_end = start
255+
step = -1
256+
}
257+
else {
258+
_start = start
259+
_end = end
260+
step = 1
261+
}
262+
var count = 0
263+
while _start != _end {
264+
count += step
265+
formIndex(after: &_start)
266+
}
267+
return count
217268
}
218269

219-
public typealias SubSequence = LazyFilterCollection<Base.SubSequence>
270+
@inline(__always)
271+
@_inlineable // FIXME(sil-serialize-all)
272+
@_versioned // FIXME(sil-serialize-all)
273+
internal func _advanceIndex(_ i: inout Index, step: Int) {
274+
repeat {
275+
_base.formIndex(&i, offsetBy: step)
276+
} while i != _base.endIndex && !_predicate(_base[i])
277+
}
220278

221279
@_inlineable // FIXME(sil-serialize-all)
222-
public subscript(bounds: Range<Index>) -> SubSequence {
223-
return SubSequence(_base: _base[bounds], _predicate)
280+
public func index(_ i: Index, offsetBy n: Int) -> Index {
281+
var i = i
282+
let step = n.signum()
283+
for _ in 0 ..< abs(numericCast(n)) {
284+
_advanceIndex(&i, step: step)
285+
}
286+
return i
224287
}
225288

226-
// Any estimate of the number of elements that pass `_predicate` requires
227-
// iterating the collection and evaluating each element, which can be costly,
228-
// is unexpected, and usually doesn't pay for itself in saving time through
229-
// preventing intermediate reallocations. (SR-4164)
230289
@_inlineable // FIXME(sil-serialize-all)
231-
public var underestimatedCount: Int { return 0 }
290+
public func formIndex(_ i: inout Index, offsetBy n: Int) {
291+
i = index(i, offsetBy: n)
292+
}
232293

233294
@_inlineable // FIXME(sil-serialize-all)
234-
public func _copyToContiguousArray()
235-
-> ContiguousArray<Base.Iterator.Element> {
295+
public func index(
296+
_ i: Index, offsetBy n: Int, limitedBy limit: Index
297+
) -> Index? {
298+
var i = i
299+
let step = n.signum()
300+
for _ in 0 ..< abs(numericCast(n)) {
301+
if i == limit {
302+
return nil
303+
}
304+
_advanceIndex(&i, step: step)
305+
}
306+
return i
307+
}
236308

237-
// The default implementation of `_copyToContiguousArray` queries the
238-
// `count` property, which evaluates `_predicate` for every element --
239-
// see the note above `underestimatedCount`. Here we treat `self` as a
240-
// sequence and only rely on underestimated count.
241-
return _copySequenceToContiguousArray(self)
309+
@_inlineable // FIXME(sil-serialize-all)
310+
public func formIndex(
311+
_ i: inout Index, offsetBy n: Int, limitedBy limit: Index
312+
) -> Bool {
313+
if let advancedIndex = index(i, offsetBy: n, limitedBy: limit) {
314+
i = advancedIndex
315+
return true
316+
}
317+
i = limit
318+
return false
242319
}
243320

244-
/// Returns an iterator over the elements of this sequence.
321+
/// Accesses the element at `position`.
245322
///
246-
/// - Complexity: O(1).
323+
/// - Precondition: `position` is a valid position in `self` and
324+
/// `position != endIndex`.
247325
@_inlineable // FIXME(sil-serialize-all)
248-
public func makeIterator() -> LazyFilterIterator<Base.Iterator> {
249-
return LazyFilterIterator(
250-
_base: _base.makeIterator(), _predicate)
326+
public subscript(position: Index) -> Base.Element {
327+
return _base[position]
251328
}
252329

253-
@_versioned // FIXME(sil-serialize-all)
254-
internal var _base: Base
255-
@_versioned // FIXME(sil-serialize-all)
256-
internal let _predicate: (Base.Element) -> Bool
330+
@_inlineable // FIXME(sil-serialize-all)
331+
public subscript(bounds: Range<Index>) -> SubSequence {
332+
return SubSequence(_base: _base[bounds], _predicate)
333+
}
257334
}
258335

259336
extension LazyFilterCollection : BidirectionalCollection

0 commit comments

Comments
 (0)