Skip to content

Commit 25a28bc

Browse files
author
Max Moiseev
committed
Enforce forward collection preconditions in LazyFilterCollection
(cherry picked from commit 229dcd6)
1 parent f2f103d commit 25a28bc

File tree

1 file changed

+23
-26
lines changed

1 file changed

+23
-26
lines changed

stdlib/public/core/Filter.swift

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -241,32 +241,6 @@ extension LazyFilterCollection : LazyCollectionProtocol, Collection {
241241
i = index
242242
}
243243

244-
@_inlineable // FIXME(sil-serialize-all)
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
268-
}
269-
270244
@inline(__always)
271245
@_inlineable // FIXME(sil-serialize-all)
272246
@_versioned // FIXME(sil-serialize-all)
@@ -276,10 +250,29 @@ extension LazyFilterCollection : LazyCollectionProtocol, Collection {
276250
} while i != _base.endIndex && !_predicate(_base[i])
277251
}
278252

253+
@inline(__always)
254+
@_inlineable // FIXME(sil-serialize-all)
255+
@_versioned // FIXME(sil-serialize-all)
256+
internal func _ensureBidirectional(step: Int) {
257+
// FIXME: This seems to be the best way of checking whether _base is
258+
// forward only without adding an extra protocol requirement.
259+
// index(_:offsetBy:limitedBy:) is chosen becuase it is supposed to return
260+
// nil when the resulting index lands outside the collection boundaries,
261+
// and therefore likely does not trap in these cases.
262+
if step < 0 {
263+
_ = _base.index(
264+
_base.endIndex, offsetBy: step, limitedBy: _base.startIndex)
265+
}
266+
}
267+
279268
@_inlineable // FIXME(sil-serialize-all)
280269
public func index(_ i: Index, offsetBy n: Int) -> Index {
281270
var i = i
282271
let step = n.signum()
272+
// The following line makes sure that index(_:offsetBy:) is invoked on the
273+
// _base at least once, to trigger a _precondition in forward only
274+
// collections.
275+
_ensureBidirectional(step: step)
283276
for _ in 0 ..< abs(numericCast(n)) {
284277
_advanceIndex(&i, step: step)
285278
}
@@ -297,6 +290,10 @@ extension LazyFilterCollection : LazyCollectionProtocol, Collection {
297290
) -> Index? {
298291
var i = i
299292
let step = n.signum()
293+
// The following line makes sure that index(_:offsetBy:limitedBy:) is
294+
// invoked on the _base at least once, to trigger a _precondition in
295+
// forward only collections.
296+
_ensureBidirectional(step: step)
300297
for _ in 0 ..< abs(numericCast(n)) {
301298
if i == limit {
302299
return nil

0 commit comments

Comments
 (0)