@@ -289,41 +289,55 @@ extension FlattenCollection: Collection {
289289
290290 @inlinable // lazy-performance
291291 public func distance( from start: Index , to end: Index ) -> Int {
292+ let minus = start > end
293+
292294 // The following check ensures that distance(from:to:) is invoked on
293295 // the _base at least once, to trigger a _precondition in forward only
294296 // collections.
295- if start > end {
297+ if minus {
296298 _ = _base. distance ( from: _base. endIndex, to: _base. startIndex)
297299 }
298300
299- // This handles indices belonging to the same collection.
301+ // This path handles indices belonging to the same collection.
300302 if start. _outer == end. _outer {
301303 guard let i = start. _inner, let j = end. _inner else { return 0 }
302304 return _base [ start. _outer] . distance ( from: i, to: j)
303305 }
304306
305- // The following combines the distance of three sections .
306- let range = start <= end ? start ..< end : end ..< start
307+ // The following path combines the distances of three regions .
308+ let range = minus ? end ..< start : start ..< end
307309 var outer = range. lowerBound. _outer
308- var count = 0 as Int // 0...Int.max
309310
311+ var distance : Int = 0
312+ let step : Int = minus ? - 1 : 1
313+
314+ // This unwrap always succeeds.
310315 if let inner = range. lowerBound. _inner {
311316 let collection = _base [ outer]
312- count += collection. distance ( from: inner, to: collection. endIndex)
313317 _base. formIndex ( after: & outer)
318+ distance += minus
319+ ? collection. distance ( from: collection. endIndex, to: inner)
320+ : collection. distance ( from: inner, to: collection. endIndex)
314321 }
315322
323+ // Using count is fine because the distance is nonzero here.
324+ // In other words, the most negative nontrapping value is -Int.max.
325+ _internalInvariant ( distance != 0 , " distance should not be zero " )
316326 while outer < range. upperBound. _outer {
317- count += _base [ outer] . count
327+ // 0...Int.max can always be negated.
328+ let collection = _base [ outer]
318329 _base. formIndex ( after: & outer)
330+ distance += collection. count &* step
319331 }
320332
321333 if let inner = range. upperBound. _inner {
322334 let collection = _base [ outer]
323- count += collection. distance ( from: collection. startIndex, to: inner)
335+ distance += minus
336+ ? collection. distance ( from: inner, to: collection. startIndex)
337+ : collection. distance ( from: collection. startIndex, to: inner)
324338 }
325339
326- return start <= end ? count : - count
340+ return distance
327341 }
328342
329343 @inline ( __always)
0 commit comments