Skip to content

Commit af0c9fa

Browse files
committed
FlattenSequence/distance(from:to:) untrapping Int.min (v6).
1. Put the first region inside the if-else (same branch condition). 2. Use the forward distance in the highest region (as done in the middle).
1 parent 7703ae4 commit af0c9fa

File tree

1 file changed

+21
-22
lines changed

1 file changed

+21
-22
lines changed

stdlib/public/core/Flatten.swift

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -290,44 +290,42 @@ extension FlattenCollection: Collection {
290290
@inlinable // lazy-performance
291291
public func distance(from start: Index, to end: Index) -> Int {
292292
let distanceIsNegative = start > end
293-
293+
294294
// The following check ensures that distance(from:to:) is invoked on
295295
// the _base at least once, to trigger a _precondition in forward only
296296
// collections.
297297
if distanceIsNegative {
298298
_ = _base.distance(from: _base.endIndex, to: _base.startIndex)
299299
}
300-
300+
301301
// This path handles indices belonging to the same collection.
302302
if start._outer == end._outer {
303303
guard let i = start._inner, let j = end._inner else { return 0 }
304304
return _base[start._outer].distance(from: i, to: j)
305305
}
306-
306+
307307
// The following path combines the distances of three regions.
308-
var distance: Int = 0
309-
let step: Int
310308
let lowerBound: Index
311309
let upperBound: Index
312-
310+
311+
let step: Int
312+
var distance: Int
313+
314+
// Note that lowerBound is a valid index because start != end.
313315
if distanceIsNegative {
314316
step = -1
315317
lowerBound = end
316318
upperBound = start
319+
let lowest = _base[lowerBound._outer]
320+
distance = lowest.distance(from: lowest.endIndex, to: lowerBound._inner!)
317321
} else {
318322
step = 01
319323
lowerBound = start
320324
upperBound = end
325+
let lowest = _base[lowerBound._outer]
326+
distance = lowest.distance(from: lowerBound._inner!, to: lowest.endIndex)
321327
}
322-
323-
// This always unwraps because start._outer != end._outer.
324-
if let inner = lowerBound._inner {
325-
let collection = _base[lowerBound._outer]
326-
distance += distanceIsNegative
327-
? collection.distance(from: collection.endIndex, to: inner)
328-
: collection.distance(from: inner, to: collection.endIndex)
329-
}
330-
328+
331329
// We can use each collection's count in the middle region since the
332330
// fast path ensures that the other regions cover a nonzero distance,
333331
// which means that an extra Int.min distance should trap regardless.
@@ -337,15 +335,16 @@ extension FlattenCollection: Collection {
337335
distance += _base[outer].count &* step
338336
_base.formIndex(after: &outer)
339337
}
340-
341-
/// This unwraps if start != endIndex and end != endIndex.
338+
339+
// This unwraps if start != endIndex and end != endIndex. We can use the
340+
// positive distance for the same reason that we can use the collection's
341+
// count in the middle region.
342342
if let inner = upperBound._inner {
343-
let collection = _base[upperBound._outer]
344-
distance += distanceIsNegative
345-
? collection.distance(from: inner, to: collection.startIndex)
346-
: collection.distance(from: collection.startIndex, to: inner)
343+
// 0 ... Int.max can always be negated.
344+
let highest = _base[upperBound._outer]
345+
distance += highest.distance(from: highest.startIndex, to: inner) &* step
347346
}
348-
347+
349348
return distance
350349
}
351350

0 commit comments

Comments
 (0)