Skip to content

Commit 37bf02f

Browse files
author
Max Moiseev
committed
[stdlib][swift-3-indexing-model] changes in index(_:stepsFrom:limitedBy:)
- index(_:stepsFrom:limitedBy:) returns Index? - formIndex(_:stepsFrom:limitedBy) returns Bool
1 parent 01d0de2 commit 37bf02f

17 files changed

+141
-99
lines changed

Diff for: stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ internal func _checkIncrementalAdvance<
109109
var offset: BaseCollection.IndexDistance = 0
110110
for _ in 0...(d * sign).toIntMax() {
111111
let j = baseCollection.index(offset, stepsFrom: i)
112-
let k = baseCollection.index(offset + sign, stepsFrom: i, limitedBy: limit)
112+
let k = baseCollection.index(offset + sign, stepsFrom: i, limitedBy: limit) ?? limit
113113
let jAtLimit = offset == d
114114
if jAtLimit {
115115
expectEqual(limit, j, ${trace})

Diff for: stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ if resiliencyChecks.subscriptRangeOnOutOfBoundsRangesBehavior != .none {
682682
}
683683
}
684684

685-
// FIXME: swift-3-indexing-model - add tests for the follow?
685+
// FIXME: swift-3-indexing-model - add tests for the following?
686686
// successor(of: i: Index) -> Index
687687
// formSuccessor(i: inout Index)
688688
// advance(i: Index, by n: IndexDistance) -> Index

Diff for: stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift.gyb

+3-1
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,9 @@ public struct ${Self}<
424424
}
425425

426426
@warn_unused_result
427-
public func index(n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index) -> Index {
427+
public func index(
428+
n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index
429+
) -> Index? {
428430
Log.advanceLimit[selfType] += 1
429431
return base.index(n, stepsFrom: i, limitedBy: limit)
430432
}

Diff for: stdlib/public/core/BidirectionalCollection.swift

+14-8
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,14 @@ extension BidirectionalIndexable {
100100
@warn_unused_result
101101
public func index(
102102
n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index
103-
) -> Index {
103+
) -> Index? {
104104
if n >= 0 {
105105
return _advanceForward(i, by: n, limitedBy: limit)
106106
}
107107
var i = i
108108
for _ in stride(from: 0, to: n, by: -1) {
109-
if (limit == i) {
110-
break;
109+
if i == limit {
110+
return nil
111111
}
112112
formPredecessor(&i)
113113
}
@@ -157,13 +157,13 @@ extension BidirectionalIndexable where Index : Strideable {
157157
}
158158

159159
@warn_unused_result
160-
public func index(n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index) -> Index {
160+
public func index(n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index) -> Index? {
161161
// FIXME: swift-3-indexing-model: range check i
162162

163163
// FIXME: swift-3-indexing-model - error: cannot invoke 'advanced' with an argument list of type '(by: Self.IndexDistance)'
164164
let i = i.advanced(by: n)
165-
if (i >= limit) {
166-
return limit
165+
if (i > limit) {
166+
return nil
167167
}
168168
return i
169169
}
@@ -235,7 +235,10 @@ extension BidirectionalCollection {
235235
public func dropLast(n: Int) -> SubSequence {
236236
_precondition(
237237
n >= 0, "Can't drop a negative number of elements from a collection")
238-
let end = index(numericCast(-n), stepsFrom: endIndex, limitedBy: startIndex)
238+
let end = index(
239+
numericCast(-n),
240+
stepsFrom: endIndex,
241+
limitedBy: startIndex) ?? startIndex
239242
return self[startIndex..<end]
240243
}
241244

@@ -252,7 +255,10 @@ extension BidirectionalCollection {
252255
_precondition(
253256
maxLength >= 0,
254257
"Can't take a suffix of negative length from a collection")
255-
let start = index(numericCast(-maxLength), stepsFrom: endIndex, limitedBy: startIndex)
258+
let start = index(
259+
numericCast(-maxLength),
260+
stepsFrom: endIndex,
261+
limitedBy: startIndex) ?? startIndex
256262
return self[start..<endIndex]
257263
}
258264
}

Diff for: stdlib/public/core/Collection.swift

+43-27
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,14 @@ public protocol Indexable : IndexableBase {
159159
@warn_unused_result
160160
func index(n: IndexDistance, stepsFrom i: Index) -> Index
161161

162-
/// Returns the result of advancing `i` by `n` positions, or until it
163-
/// equals `limit`.
162+
/// Returns the result of advancing `i` by `n` positions, or `nil` if it
163+
/// reaches the `limit`.
164164
///
165165
/// - Returns:
166-
/// - If `n > 0`, the `n`th successor of `i` or `limit`, whichever
167-
/// is reached first.
168-
/// - If `n < 0`, the `n`th predecessor of `i` or `limit`, whichever
169-
/// is reached first.
166+
/// - If `n > 0`, the `n`th successor of `i` or `nil` if the `limit` has
167+
/// been reached.
168+
/// - If `n < 0`, the `n`th predecessor of `i` or `nil` if the `limit` has
169+
/// been reached.
170170
/// - Otherwise, `i` unmodified.
171171
///
172172
/// - Precondition: `n >= 0` unless `Self` conforms to
@@ -178,7 +178,7 @@ public protocol Indexable : IndexableBase {
178178
@warn_unused_result
179179
func index(
180180
n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index
181-
) -> Index
181+
) -> Index?
182182

183183
/// Advances `i` by `n` positions.
184184
///
@@ -195,6 +195,9 @@ public protocol Indexable : IndexableBase {
195195

196196
/// Advances `i` by `n` positions, or until it equals `limit`.
197197
///
198+
/// - Returns `true` if index has been advanced by exactly `n` steps without
199+
/// reaching the `limit`, and `false` otherwise.
200+
///
198201
/// - Precondition: `n >= 0` unless `Self` conforms to
199202
/// `BidirectionalCollection`.
200203
///
@@ -203,7 +206,7 @@ public protocol Indexable : IndexableBase {
203206
/// - O(`abs(n)`) otherwise.
204207
func formIndex(
205208
n: IndexDistance, stepsFrom i: inout Index, limitedBy limit: Index
206-
)
209+
) -> Bool
207210

208211
/// Returns the distance between `start` and `end`.
209212
///
@@ -406,14 +409,14 @@ public protocol Collection : Indexable, Sequence {
406409
func index(n: IndexDistance, stepsFrom i: Index) -> Index
407410

408411
// FIXME: swift-3-indexing-model: Should this mention preconditions on `n`?
409-
/// Returns the result of advancing `i` by `n` positions, or until it
410-
/// equals `limit`.
412+
/// Returns the result of advancing `i` by `n` positions, or `nil` if it
413+
/// reaches the `limit`.
411414
///
412415
/// - Returns:
413-
/// - If `n > 0`, the `n`th successor of `i` or `limit`, whichever
414-
/// is reached first.
415-
/// - If `n < 0`, the `n`th predecessor of `i` or `limit`, whichever
416-
/// is reached first.
416+
/// - If `n > 0`, the `n`th successor of `i` or `nil` if the `limit` has
417+
/// been reached.
418+
/// - If `n < 0`, the `n`th predecessor of `i` or `nil` if the `limit` has
419+
/// been reached.
417420
/// - Otherwise, `i` unmodified.
418421
///
419422
/// - Precondition: `n >= 0` unless `Self` conforms to
@@ -425,7 +428,7 @@ public protocol Collection : Indexable, Sequence {
425428
@warn_unused_result
426429
func index(
427430
n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index
428-
) -> Index
431+
) -> Index?
429432

430433
/// Returns the distance between `start` and `end`.
431434
///
@@ -481,7 +484,7 @@ extension Indexable {
481484
@warn_unused_result
482485
public func index(
483486
n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index
484-
) -> Index {
487+
) -> Index? {
485488
// FIXME: swift-3-indexing-model: tests.
486489
return self._advanceForward(i, by: n, limitedBy: limit)
487490
}
@@ -492,8 +495,13 @@ extension Indexable {
492495

493496
public func formIndex(
494497
n: IndexDistance, stepsFrom i: inout Index, limitedBy limit: Index
495-
) {
496-
i = index(n, stepsFrom: i, limitedBy: limit)
498+
) -> Bool {
499+
if let advancedIndex = index(n, stepsFrom: i, limitedBy: limit) {
500+
i = advancedIndex
501+
return true
502+
}
503+
i = limit
504+
return false
497505
}
498506

499507
@warn_unused_result
@@ -529,14 +537,16 @@ extension Indexable {
529537
@inline(__always)
530538
@warn_unused_result
531539
internal
532-
func _advanceForward(i: Index, by n: IndexDistance, limitedBy limit: Index) -> Index {
540+
func _advanceForward(
541+
i: Index, by n: IndexDistance, limitedBy limit: Index
542+
) -> Index? {
533543
_precondition(n >= 0,
534544
"Only BidirectionalCollections can be advanced by a negative amount")
535545

536546
var i = i
537547
for _ in stride(from: 0, to: n, by: 1) {
538-
if (limit == i) {
539-
break;
548+
if i == limit {
549+
return nil
540550
}
541551
formSuccessor(&i)
542552
}
@@ -567,15 +577,17 @@ extension Indexable where Index : Strideable {
567577
}
568578

569579
@warn_unused_result
570-
public func index(n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index) -> Index {
580+
public func index(
581+
n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index
582+
) -> Index? {
571583
_precondition(n >= 0,
572584
"Only BidirectionalCollections can be advanced by a negative amount")
573585
// FIXME: swift-3-indexing-model: range check i
574586

575587
// FIXME: swift-3-indexing-model - error: cannot invoke 'advanced' with an argument list of type '(by: Self.IndexDistance)'
576588
let i = i.advanced(by: n)
577589
if (i >= limit) {
578-
return limit
590+
return nil
579591
}
580592
return i
581593
}
@@ -728,7 +740,8 @@ extension Collection {
728740
@warn_unused_result
729741
public func dropFirst(n: Int) -> SubSequence {
730742
_precondition(n >= 0, "Can't drop a negative number of elements from a collection")
731-
let start = index(numericCast(n), stepsFrom: startIndex, limitedBy: endIndex)
743+
let start = index(numericCast(n),
744+
stepsFrom: startIndex, limitedBy: endIndex) ?? endIndex
732745
return self[start..<endIndex]
733746
}
734747

@@ -741,7 +754,8 @@ extension Collection {
741754
_precondition(
742755
n >= 0, "Can't drop a negative number of elements from a collection")
743756
let amount = Swift.max(0, numericCast(count) - n)
744-
let end = index(numericCast(amount), stepsFrom: startIndex, limitedBy: endIndex)
757+
let end = index(numericCast(amount),
758+
stepsFrom: startIndex, limitedBy: endIndex) ?? endIndex
745759
return self[startIndex..<end]
746760
}
747761

@@ -758,7 +772,8 @@ extension Collection {
758772
_precondition(
759773
maxLength >= 0,
760774
"Can't take a prefix of negative length from a collection")
761-
let end = index(numericCast(maxLength), stepsFrom: startIndex, limitedBy: endIndex)
775+
let end = index(numericCast(maxLength),
776+
stepsFrom: startIndex, limitedBy: endIndex) ?? endIndex
762777
return self[startIndex..<end]
763778
}
764779

@@ -776,7 +791,8 @@ extension Collection {
776791
maxLength >= 0,
777792
"Can't take a suffix of negative length from a collection")
778793
let amount = Swift.max(0, numericCast(count) - maxLength)
779-
let start = index(numericCast(amount), stepsFrom: startIndex, limitedBy: endIndex)
794+
let start = index(numericCast(amount),
795+
stepsFrom: startIndex, limitedBy: endIndex) ?? endIndex
780796
return self[start..<endIndex]
781797
}
782798

Diff for: stdlib/public/core/EmptyCollection.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ public struct EmptyCollection<Element> :
110110
/// EmptyCollection does not have any element indices, so it is not
111111
/// possible to advance indices.
112112
@warn_unused_result
113-
public func index(n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index) -> Index {
113+
public func index(
114+
n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index
115+
) -> Index? {
114116
// TODO: swift-3-indexing-model: tests for traps.
115117
_preconditionFailure("EmptyCollection can't advance indices")
116118
}

Diff for: stdlib/public/core/ExistentialCollection.swift.gyb

+21-17
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ internal class _AnyRandomAccessCollectionBox<Element>
232232
n: IntMax,
233233
stepsFrom i: _AnyIndexBox,
234234
limitedBy limit: _AnyIndexBox
235-
) -> _AnyIndexBox {
235+
) -> _AnyIndexBox? {
236236
_abstract()
237237
}
238238
internal func _formIndex(n: IntMax, stepsFrom i: inout _AnyIndexBox) {
@@ -242,7 +242,7 @@ internal class _AnyRandomAccessCollectionBox<Element>
242242
n: IntMax,
243243
stepsFrom i: inout _AnyIndexBox,
244244
limitedBy limit: _AnyIndexBox
245-
) {
245+
) -> Bool {
246246
_abstract()
247247
}
248248
@warn_unused_result
@@ -493,20 +493,20 @@ internal final class _${Kind}Box<
493493
n: IntMax,
494494
stepsFrom i: _AnyIndexBox,
495495
limitedBy limit: _AnyIndexBox
496-
) -> _AnyIndexBox {
497-
return _IndexBox(_base:
498-
_base.index(
496+
) -> _AnyIndexBox? {
497+
return _base.index(
499498
numericCast(n),
500499
stepsFrom: _unbox(i),
501-
limitedBy: _unbox(limit)))
500+
limitedBy: _unbox(limit))
501+
.map { _IndexBox(_base: $0) }
502502
}
503503

504504
internal override func _formIndex(
505505
n: IntMax,
506506
stepsFrom i: inout _AnyIndexBox
507507
) {
508-
if let i = i as? _IndexBox<S.Index> {
509-
return _base.formIndex(numericCast(n), stepsFrom: &i._base)
508+
if let box = i as? _IndexBox<S.Index> {
509+
return _base.formIndex(numericCast(n), stepsFrom: &box._base)
510510
}
511511
fatalError("Index type mismatch!")
512512
}
@@ -515,11 +515,11 @@ internal final class _${Kind}Box<
515515
n: IntMax,
516516
stepsFrom i: inout _AnyIndexBox,
517517
limitedBy limit: _AnyIndexBox
518-
) {
519-
if let i = i as? _IndexBox<S.Index> {
518+
) -> Bool {
519+
if let box = i as? _IndexBox<S.Index> {
520520
return _base.formIndex(
521521
numericCast(n),
522-
stepsFrom: &i._base,
522+
stepsFrom: &box._base,
523523
limitedBy: _unbox(limit))
524524
}
525525
fatalError("Index type mismatch!")
@@ -1029,9 +1029,9 @@ public struct ${Self}<Element>
10291029
n: IntMax,
10301030
stepsFrom i: AnyIndex,
10311031
limitedBy limit: AnyIndex
1032-
) -> AnyIndex {
1033-
return AnyIndex(
1034-
_box: _box._index(n, stepsFrom: i._box, limitedBy: limit._box))
1032+
) -> AnyIndex? {
1033+
return _box._index(n, stepsFrom: i._box, limitedBy: limit._box)
1034+
.map { AnyIndex(_box:$0) }
10351035
}
10361036

10371037
public func formIndex(n: IntMax, stepsFrom i: inout AnyIndex) {
@@ -1046,12 +1046,16 @@ public struct ${Self}<Element>
10461046
n: IntMax,
10471047
stepsFrom i: inout AnyIndex,
10481048
limitedBy limit: AnyIndex
1049-
) {
1049+
) -> Bool {
10501050
if _isUnique(&i._box) {
10511051
return _box._formIndex(n, stepsFrom: &i._box, limitedBy: limit._box)
1052-
} else {
1053-
i = index(n, stepsFrom: i, limitedBy: limit)
10541052
}
1053+
if let advanced = index(n, stepsFrom: i, limitedBy: limit) {
1054+
i = advanced
1055+
return true
1056+
}
1057+
i = limit
1058+
return false
10551059
}
10561060

10571061
@warn_unused_result

Diff for: stdlib/public/core/Filter.swift

+4-2
Original file line numberDiff line numberDiff line change
@@ -233,15 +233,17 @@ public struct LazyFilterCollection<
233233

234234
// TODO: swift-3-indexing-model - add docs
235235
@warn_unused_result
236-
public func index(n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index) -> Index {
236+
public func index(
237+
n: IndexDistance, stepsFrom i: Index, limitedBy limit: Index
238+
) -> Index? {
237239
_precondition(n >= 0,
238240
"Only BidirectionalCollections can be advanced by a negative amount")
239241
// TODO: swift-3-indexing-model: _failEarlyRangeCheck i?
240242

241243
var index = i.base
242244
for _ in stride(from: 0, to: n, by: 1) {
243245
if index == limit.base {
244-
break
246+
return nil
245247
}
246248
_nextFilteredInPlace(&index)
247249
}

0 commit comments

Comments
 (0)