Skip to content

Commit 0646c61

Browse files
committed
Fix bidirectional test to account for RandomAccess
1 parent b0d9854 commit 0646c61

File tree

2 files changed

+165
-4
lines changed

2 files changed

+165
-4
lines changed

stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,167 @@ public struct MinimalBidirectionalCollection<T> : BidirectionalCollection {
16151615
internal let _collectionState: _CollectionState
16161616
}
16171617

1618+
/// A minimal implementation of `Collection` with extra checks.
1619+
public struct MinimalBidirectionalRandomAccessCollection<T> : BidirectionalCollection, RandomAccessCollection {
1620+
/// Creates a collection with given contents, but a unique modification
1621+
/// history. No other instance has the same modification history.
1622+
public init<S : Sequence>(
1623+
elements: S,
1624+
underestimatedCount: UnderestimatedCountBehavior = .value(0)
1625+
) where S.Element == T {
1626+
self._elements = Array(elements)
1627+
1628+
self._collectionState = _CollectionState(
1629+
newRootStateForElementCount: self._elements.count)
1630+
1631+
switch underestimatedCount {
1632+
case .precise:
1633+
self.underestimatedCount = _elements.count
1634+
1635+
case .half:
1636+
self.underestimatedCount = _elements.count / 2
1637+
1638+
case .overestimate:
1639+
self.underestimatedCount = _elements.count * 3 + 5
1640+
1641+
case .value(let count):
1642+
self.underestimatedCount = count
1643+
}
1644+
}
1645+
1646+
1647+
public let timesMakeIteratorCalled = ResettableValue(0)
1648+
1649+
public func makeIterator() -> MinimalIterator<T> {
1650+
timesMakeIteratorCalled.value += 1
1651+
return MinimalIterator(_elements)
1652+
}
1653+
1654+
public typealias Index = MinimalIndex
1655+
1656+
internal func _index(forPosition i: Int) -> MinimalIndex {
1657+
return MinimalIndex(
1658+
collectionState: _collectionState,
1659+
position: i,
1660+
startIndex: _elements.startIndex,
1661+
endIndex: _elements.endIndex)
1662+
}
1663+
1664+
internal func _uncheckedIndex(forPosition i: Int) -> MinimalIndex {
1665+
return MinimalIndex(
1666+
_collectionState: _collectionState,
1667+
uncheckedPosition: i)
1668+
}
1669+
1670+
public let timesStartIndexCalled = ResettableValue(0)
1671+
1672+
public var startIndex: MinimalIndex {
1673+
timesStartIndexCalled.value += 1
1674+
return _uncheckedIndex(forPosition: _elements.startIndex)
1675+
}
1676+
1677+
public let timesEndIndexCalled = ResettableValue(0)
1678+
1679+
public var endIndex: MinimalIndex {
1680+
timesEndIndexCalled.value += 1
1681+
return _uncheckedIndex(forPosition: _elements.endIndex)
1682+
}
1683+
1684+
1685+
public func _failEarlyRangeCheck(
1686+
_ index: MinimalIndex,
1687+
bounds: Range<MinimalIndex>
1688+
) {
1689+
_expectCompatibleIndices(
1690+
_uncheckedIndex(forPosition: index.position),
1691+
index)
1692+
1693+
_expectCompatibleIndices(
1694+
_uncheckedIndex(forPosition: bounds.lowerBound.position),
1695+
bounds.lowerBound)
1696+
_expectCompatibleIndices(
1697+
_uncheckedIndex(forPosition: bounds.upperBound.position),
1698+
bounds.upperBound)
1699+
1700+
expectTrapping(
1701+
index.position,
1702+
in: bounds.lowerBound.position..<bounds.upperBound.position)
1703+
}
1704+
1705+
public func _failEarlyRangeCheck(
1706+
_ range: Range<MinimalIndex>,
1707+
bounds: Range<MinimalIndex>
1708+
) {
1709+
_expectCompatibleIndices(
1710+
_uncheckedIndex(forPosition: range.lowerBound.position),
1711+
range.lowerBound)
1712+
_expectCompatibleIndices(
1713+
_uncheckedIndex(forPosition: range.upperBound.position),
1714+
range.upperBound)
1715+
1716+
_expectCompatibleIndices(
1717+
_uncheckedIndex(forPosition: bounds.lowerBound.position),
1718+
bounds.lowerBound)
1719+
_expectCompatibleIndices(
1720+
_uncheckedIndex(forPosition: bounds.upperBound.position),
1721+
bounds.upperBound)
1722+
1723+
expectTrapping(
1724+
range.lowerBound.position..<range.upperBound.position,
1725+
in: bounds.lowerBound.position..<bounds.upperBound.position)
1726+
}
1727+
1728+
public func index(after i: MinimalIndex) -> MinimalIndex {
1729+
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
1730+
return _uncheckedIndex(forPosition: i.position + 1)
1731+
}
1732+
1733+
public func index(before i: MinimalIndex) -> MinimalIndex {
1734+
// FIXME: swift-3-indexing-model: perform a range check and use
1735+
// return _uncheckedIndex(forPosition: i.position - 1)
1736+
return _index(forPosition: i.position - 1)
1737+
}
1738+
1739+
public func distance(from start: MinimalIndex, to end: MinimalIndex)
1740+
-> Int {
1741+
// FIXME: swift-3-indexing-model: perform a range check properly.
1742+
if start != endIndex {
1743+
_failEarlyRangeCheck(start, bounds: startIndex..<endIndex)
1744+
}
1745+
if end != endIndex {
1746+
_failEarlyRangeCheck(end, bounds: startIndex..<endIndex)
1747+
}
1748+
return end.position - start.position
1749+
}
1750+
1751+
public func index(_ i: Index, offsetBy n: Int) -> Index {
1752+
// FIXME: swift-3-indexing-model: perform a range check properly.
1753+
if i != endIndex {
1754+
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
1755+
}
1756+
return _index(forPosition: i.position + n)
1757+
}
1758+
1759+
public subscript(i: MinimalIndex) -> T {
1760+
get {
1761+
_failEarlyRangeCheck(i, bounds: startIndex..<endIndex)
1762+
return _elements[i.position]
1763+
}
1764+
}
1765+
1766+
public subscript(bounds: Range<MinimalIndex>) -> Slice<MinimalBidirectionalCollection<T>> {
1767+
get {
1768+
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
1769+
return Slice(base: self, bounds: bounds)
1770+
}
1771+
}
1772+
1773+
1774+
public var underestimatedCount: Int
1775+
1776+
internal var _elements: [T]
1777+
internal let _collectionState: _CollectionState
1778+
}
16181779

16191780
/// A minimal implementation of `Collection` with extra checks.
16201781
public struct MinimalRangeReplaceableBidirectionalCollection<T> : BidirectionalCollection, RangeReplaceableCollection {

validation-test/stdlib/SequenceType.swift.gyb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ SequenceTypeTests.test("enumerated()/Sequence") {
275275
}
276276

277277
SequenceTypeTests.test("enumerated()/Collection") {
278-
guard #available(SwiftStdlib 6.1, *) else { return }
278+
guard #available(SwiftStdlib 6.2, *) else { return }
279279

280280
typealias Element = (offset: Int, element: OpaqueValue<Int>)
281281
func compareElements(_ lhs: Element, rhs: Element) -> Bool {
@@ -300,7 +300,7 @@ SequenceTypeTests.test("enumerated()/Collection") {
300300
}
301301

302302
SequenceTypeTests.test("enumerated()/BidirectionalCollection") {
303-
guard #available(SwiftStdlib 6.1, *) else { return }
303+
guard #available(SwiftStdlib 6.2, *) else { return }
304304

305305
typealias Element = (offset: Int, element: OpaqueValue<Int>)
306306
func compareElements(_ lhs: Element, rhs: Element) -> Bool {
@@ -312,7 +312,7 @@ SequenceTypeTests.test("enumerated()/BidirectionalCollection") {
312312
elements: test.sequence.map(OpaqueValue.init))
313313
var result = s.enumerated()
314314
expectType(
315-
EnumeratedSequence<MinimalBidirectionalCollection<OpaqueValue<Int>>>.self,
315+
EnumeratedSequence<MinimalBidirectionalRandomAccessCollection<OpaqueValue<Int>>>.self,
316316
&result)
317317

318318
checkBidirectionalCollection(
@@ -325,7 +325,7 @@ SequenceTypeTests.test("enumerated()/BidirectionalCollection") {
325325
}
326326

327327
SequenceTypeTests.test("enumerated()/RandomAccessCollection") {
328-
guard #available(SwiftStdlib 6.1, *) else { return }
328+
guard #available(SwiftStdlib 6.2, *) else { return }
329329

330330
typealias Element = (offset: Int, element: OpaqueValue<Int>)
331331
func compareElements(_ lhs: Element, rhs: Element) -> Bool {

0 commit comments

Comments
 (0)