Skip to content

Commit 72948ca

Browse files
Max Moiseevmoiseev
authored andcommitted
[stdlib] Improve default implementation of Collection.distance(from:to:)
1 parent f71456e commit 72948ca

File tree

3 files changed

+18
-26
lines changed

3 files changed

+18
-26
lines changed

stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,11 +1584,6 @@ extension TestSuite {
15841584
.forEach(in: distanceFromToTests) {
15851585
test in
15861586
let c = toCollection(0..<20)
1587-
let backwards = (test.startOffset > test.endOffset)
1588-
if backwards && !collectionIsBidirectional {
1589-
expectCrashLater()
1590-
}
1591-
15921587
let d = c.distance(
15931588
from: c.nthIndex(test.startOffset), to: c.nthIndex(test.endOffset))
15941589
expectEqual(

stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift.gyb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -662,8 +662,6 @@ public struct ${Self}<T> : ${SelfProtocols} {
662662
public func distance(from start: ${Index}, to end: ${Index})
663663
-> IndexDistance {
664664
% if Traversal == 'Forward':
665-
_precondition(start <= end,
666-
"Only BidirectionalCollections can have end come before start")
667665
% end
668666
// FIXME: swift-3-indexing-model: perform a range check properly.
669667
if start != endIndex {

stdlib/public/core/Collection.swift

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -707,16 +707,11 @@ public protocol Collection: Sequence where SubSequence: Collection {
707707

708708
/// Returns the distance between two indices.
709709
///
710-
/// Unless the collection conforms to the `BidirectionalCollection` protocol,
711-
/// `start` must be less than or equal to `end`.
712-
///
713710
/// - Parameters:
714711
/// - start: A valid index of the collection.
715712
/// - end: Another valid index of the collection. If `end` is equal to
716713
/// `start`, the result is zero.
717-
/// - Returns: The distance between `start` and `end`. The result can be
718-
/// negative only if the collection conforms to the
719-
/// `BidirectionalCollection` protocol.
714+
/// - Returns: The distance between `start` and `end`.
720715
///
721716
/// - Complexity: O(1) if the collection conforms to
722717
/// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the
@@ -965,30 +960,34 @@ extension Collection {
965960

966961
/// Returns the distance between two indices.
967962
///
968-
/// Unless the collection conforms to the `BidirectionalCollection` protocol,
969-
/// `start` must be less than or equal to `end`.
970-
///
971963
/// - Parameters:
972964
/// - start: A valid index of the collection.
973965
/// - end: Another valid index of the collection. If `end` is equal to
974966
/// `start`, the result is zero.
975-
/// - Returns: The distance between `start` and `end`. The result can be
976-
/// negative only if the collection conforms to the
977-
/// `BidirectionalCollection` protocol.
967+
/// - Returns: The distance between `start` and `end`.
978968
///
979969
/// - Complexity: O(1) if the collection conforms to
980970
/// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the
981971
/// resulting distance.
982972
@_inlineable
983973
public func distance(from start: Index, to end: Index) -> IndexDistance {
984-
_precondition(start <= end,
985-
"Only BidirectionalCollections can have end come before start")
986-
987-
var start = start
974+
var _start: Index
975+
let _end: Index
976+
let step: IndexDistance
977+
if start > end {
978+
_start = end
979+
_end = start
980+
step = -1
981+
}
982+
else {
983+
_start = start
984+
_end = end
985+
step = 1
986+
}
988987
var count: IndexDistance = 0
989-
while start != end {
990-
count = count + 1
991-
formIndex(after: &start)
988+
while _start != _end {
989+
count += step
990+
formIndex(after: &_start)
992991
}
993992
return count
994993
}

0 commit comments

Comments
 (0)