@@ -241,32 +241,6 @@ extension LazyFilterCollection : LazyCollectionProtocol, Collection {
241
241
i = index
242
242
}
243
243
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
-
270
244
@inline ( __always)
271
245
@_inlineable // FIXME(sil-serialize-all)
272
246
@_versioned // FIXME(sil-serialize-all)
@@ -276,10 +250,29 @@ extension LazyFilterCollection : LazyCollectionProtocol, Collection {
276
250
} while i != _base. endIndex && !_predicate( _base [ i] )
277
251
}
278
252
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
+
279
268
@_inlineable // FIXME(sil-serialize-all)
280
269
public func index( _ i: Index , offsetBy n: Int ) -> Index {
281
270
var i = i
282
271
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)
283
276
for _ in 0 ..< abs ( numericCast ( n) ) {
284
277
_advanceIndex ( & i, step: step)
285
278
}
@@ -297,6 +290,10 @@ extension LazyFilterCollection : LazyCollectionProtocol, Collection {
297
290
) -> Index ? {
298
291
var i = i
299
292
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)
300
297
for _ in 0 ..< abs ( numericCast ( n) ) {
301
298
if i == limit {
302
299
return nil
0 commit comments