Skip to content

Commit e4f94a3

Browse files
author
Max Moiseev
committed
[stdlib] Improve default implementation of Collection.distance(from:to:)
(cherry picked from commit 72948ca)
1 parent 229dcd6 commit e4f94a3

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
@@ -657,8 +657,6 @@ public struct ${Self}<T> : ${SelfProtocols} {
657657
public func distance(from start: ${Index}, to end: ${Index})
658658
-> Int {
659659
% if Traversal == 'Forward':
660-
_precondition(start <= end,
661-
"Only BidirectionalCollections can have end come before start")
662660
% end
663661
// FIXME: swift-3-indexing-model: perform a range check properly.
664662
if start != endIndex {

stdlib/public/core/Collection.swift

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

702702
/// Returns the distance between two indices.
703703
///
704-
/// Unless the collection conforms to the `BidirectionalCollection` protocol,
705-
/// `start` must be less than or equal to `end`.
706-
///
707704
/// - Parameters:
708705
/// - start: A valid index of the collection.
709706
/// - end: Another valid index of the collection. If `end` is equal to
710707
/// `start`, the result is zero.
711-
/// - Returns: The distance between `start` and `end`. The result can be
712-
/// negative only if the collection conforms to the
713-
/// `BidirectionalCollection` protocol.
708+
/// - Returns: The distance between `start` and `end`.
714709
///
715710
/// - Complexity: O(1) if the collection conforms to
716711
/// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the
@@ -962,30 +957,34 @@ extension Collection {
962957

963958
/// Returns the distance between two indices.
964959
///
965-
/// Unless the collection conforms to the `BidirectionalCollection` protocol,
966-
/// `start` must be less than or equal to `end`.
967-
///
968960
/// - Parameters:
969961
/// - start: A valid index of the collection.
970962
/// - end: Another valid index of the collection. If `end` is equal to
971963
/// `start`, the result is zero.
972-
/// - Returns: The distance between `start` and `end`. The result can be
973-
/// negative only if the collection conforms to the
974-
/// `BidirectionalCollection` protocol.
964+
/// - Returns: The distance between `start` and `end`.
975965
///
976966
/// - Complexity: O(1) if the collection conforms to
977967
/// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the
978968
/// resulting distance.
979969
@_inlineable
980970
public func distance(from start: Index, to end: Index) -> Int {
981-
_precondition(start <= end,
982-
"Only BidirectionalCollections can have end come before start")
983-
984-
var start = start
971+
var _start: Index
972+
let _end: Index
973+
let step: Int
974+
if start > end {
975+
_start = end
976+
_end = start
977+
step = -1
978+
}
979+
else {
980+
_start = start
981+
_end = end
982+
step = 1
983+
}
985984
var count = 0
986-
while start != end {
987-
count = count + 1
988-
formIndex(after: &start)
985+
while _start != _end {
986+
count += step
987+
formIndex(after: &_start)
989988
}
990989
return count
991990
}

0 commit comments

Comments
 (0)