Skip to content

Commit e8db705

Browse files
committed
FlattenSequence/distance(from:to:) untrapping Int.min (v2).
A better, albeit a bit more verbose, method.
1 parent 401f8d1 commit e8db705

File tree

1 file changed

+26
-17
lines changed

1 file changed

+26
-17
lines changed

stdlib/public/core/Flatten.swift

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -305,33 +305,42 @@ extension FlattenCollection: Collection {
305305
}
306306

307307
// The following path combines the distances of three regions.
308-
let range = minus ? end ..< start : start ..< end
309-
var outer = range.lowerBound._outer
310-
311308
var distance: Int = 0
312-
let step: Int = minus ? -1 : 1
309+
let step: Int
310+
let lowerBound: Index
311+
let upperBound: Index
313312

314-
// This unwrap always succeeds.
315-
if let inner = range.lowerBound._inner {
316-
let collection = _base[outer]
317-
_base.formIndex(after: &outer)
313+
if minus {
314+
lowerBound = end
315+
upperBound = start
316+
step = -1
317+
} else {
318+
lowerBound = start
319+
upperBound = end
320+
step = 01
321+
}
322+
323+
// This always unwraps because start._outer != end._outer.
324+
if let inner = lowerBound._inner {
325+
let collection = _base[lowerBound._outer]
318326
distance += minus
319327
? collection.distance(from: collection.endIndex, to: inner)
320328
: collection.distance(from: inner, to: collection.endIndex)
321329
}
322330

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")
326-
while outer < range.upperBound._outer {
327-
// 0...Int.max can always be negated.
328-
let collection = _base[outer]
331+
// We can use each collection's count in the middle region since the
332+
// fast path ensures that the other regions cover a nonzero distance,
333+
// which means that an extra Int.min distance should trap regardless.
334+
var outer = _base.index(after: lowerBound._outer)
335+
while outer < upperBound._outer {
336+
// 0 ... Int.max can always be negated.
337+
distance += _base[outer].count &* step
329338
_base.formIndex(after: &outer)
330-
distance += collection.count &* step
331339
}
332340

333-
if let inner = range.upperBound._inner {
334-
let collection = _base[outer]
341+
/// This unwraps if start != endIndex and end != endIndex.
342+
if let inner = upperBound._inner {
343+
let collection = _base[upperBound._outer]
335344
distance += minus
336345
? collection.distance(from: inner, to: collection.startIndex)
337346
: collection.distance(from: collection.startIndex, to: inner)

0 commit comments

Comments
 (0)