Skip to content

Commit 909c63d

Browse files
committed
Merge pull request #2388 from apple/stdlib-collectionofone-fixes-tests
2 parents 656c393 + f82ca83 commit 909c63d

File tree

4 files changed

+170
-40
lines changed

4 files changed

+170
-40
lines changed

stdlib/public/core/CollectionOfOne.swift

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,16 @@ public struct IteratorOverOne<Element> : IteratorProtocol, Sequence {
3535
}
3636

3737
/// A collection containing a single element of type `Element`.
38-
public struct CollectionOfOne<Element> : RandomAccessCollection {
39-
40-
// FIXME: swift-3-indexing-model - compiler bug prevents this
41-
// typealias from being sufficient. Instead we need to define the
42-
// var below.
43-
//
44-
// public typealias indices = CountableRange<Int>
45-
public var indices: CountableRange<Int> {
46-
return startIndex..<endIndex
47-
}
38+
public struct CollectionOfOne<Element>
39+
: MutableCollection, RandomAccessCollection {
4840

4941
/// Construct an instance containing just `element`.
5042
public init(_ element: Element) {
5143
self._element = element
5244
}
5345

46+
public typealias Index = Int
47+
5448
/// The position of the first element.
5549
public var startIndex: Int {
5650
return 0
@@ -71,6 +65,15 @@ public struct CollectionOfOne<Element> : RandomAccessCollection {
7165
return endIndex
7266
}
7367

68+
/// Always returns `startIndex`.
69+
@warn_unused_result
70+
public func index(before i: Int) -> Int {
71+
_precondition(i == endIndex)
72+
return endIndex
73+
}
74+
75+
public typealias Indices = CountableRange<Int>
76+
7477
/// Returns an iterator over the elements of this sequence.
7578
///
7679
/// - Complexity: O(1).
@@ -82,16 +85,45 @@ public struct CollectionOfOne<Element> : RandomAccessCollection {
8285
///
8386
/// - Precondition: `position == 0`.
8487
public subscript(position: Int) -> Element {
85-
_precondition(position == 0, "Index out of range")
86-
return _element
88+
get {
89+
_precondition(position == 0, "Index out of range")
90+
return _element
91+
}
92+
set {
93+
_precondition(position == 0, "Index out of range")
94+
_element = newValue
95+
}
96+
}
97+
98+
public subscript(bounds: Range<Int>)
99+
-> MutableRandomAccessSlice<CollectionOfOne<Element>> {
100+
get {
101+
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
102+
return MutableRandomAccessSlice(base: self, bounds: bounds)
103+
}
104+
set {
105+
_failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
106+
precondition(bounds.count == newValue.count,
107+
"CollectionOfOne can't be resized")
108+
if let newElement = newValue.first {
109+
_element = newElement
110+
}
111+
}
87112
}
88113

89114
/// The number of elements (always one).
90115
public var count: Int {
91116
return 1
92117
}
93118

94-
internal let _element: Element
119+
internal var _element: Element
120+
}
121+
122+
extension CollectionOfOne : CustomDebugStringConvertible {
123+
/// A textual representation of `self`, suitable for debugging.
124+
public var debugDescription: String {
125+
return "CollectionOfOne(\(String(reflecting: _element)))"
126+
}
95127
}
96128

97129
extension CollectionOfOne : CustomReflectable {

test/1_stdlib/DictionaryLiteral.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,17 @@ extension DictionaryLiteral where Key : TestProtocol1, Value : TestProtocol1 {
2828
}
2929
}
3030

31+
func checkAssociatedTypes() {
32+
typealias Subject = DictionaryLiteral<MinimalHashableValue, OpaqueValue<Int>>
33+
expectRandomAccessCollectionAssociatedTypes(
34+
collectionType: Subject.self,
35+
iteratorType: IndexingIterator<Subject>.self,
36+
subSequenceType: RandomAccessSlice<Subject>.self,
37+
indexType: Int.self,
38+
indexDistanceType: Int.self,
39+
indicesType: CountableRange<Int>.self)
40+
}
41+
3142
var strings: DictionaryLiteral = ["a": "1", "b": "Foo"]
3243
expectType(DictionaryLiteral<String, String>.self, &strings)
3344

test/1_stdlib/Reflection.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,6 @@ dump(justSomeFunction as Any)
164164
// CHECK-NEXT: Swift.String
165165
dump(String.self)
166166

167-
// CHECK-NEXT: Swift.CollectionOfOne<Swift.String>
168-
// CHECK-NEXT: element: "Howdy Swift!"
169-
dump(CollectionOfOne("Howdy Swift!"))
170-
171-
// CHECK-NEXT: EmptyCollection
172-
var emptyCollectionOfInt: EmptyCollection<Int> = EmptyCollection()
173-
dump(emptyCollectionOfInt)
174-
175167
// CHECK-NEXT: ▿
176168
// CHECK-NEXT: from: 1.0
177169
// CHECK-NEXT: through: 12.15

validation-test/stdlib/Lazy.swift.gyb

Lines changed: 114 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,25 +56,6 @@ LazyTestSuite.test("Repeated") {
5656

5757
// FIXME: trap tests.
5858

59-
//===----------------------------------------------------------------------===//
60-
// CollectionOfOne
61-
//===----------------------------------------------------------------------===//
62-
63-
// Check that the generic parameter is called 'Element'.
64-
extension CollectionOfOne where Element : TestProtocol1 {
65-
var _elementIsTestProtocol1: Bool {
66-
fatalError("not implemented")
67-
}
68-
}
69-
70-
LazyTestSuite.test("CollectionOfOne") {
71-
checkRandomAccessCollection(
72-
[ OpaqueValue(42) ],
73-
CollectionOfOne(OpaqueValue(42))) { $0.value == $1.value }
74-
}
75-
76-
// FIXME: trap tests.
77-
7859
//===----------------------------------------------------------------------===//
7960
// IteratorOverOne
8061
//===----------------------------------------------------------------------===//
@@ -98,6 +79,111 @@ LazyTestSuite.test("IteratorOverOne") {
9879
{ $0.value == $1.value }
9980
}
10081

82+
//===----------------------------------------------------------------------===//
83+
// ColectionOfOne
84+
//===----------------------------------------------------------------------===//
85+
86+
// Check that the generic parameter is called 'Element'.
87+
extension CollectionOfOne where Element : TestProtocol1 {
88+
var _elementIsTestProtocol1: Bool {
89+
fatalError("not implemented")
90+
}
91+
}
92+
93+
LazyTestSuite.test("CollectionOfOne") {
94+
let c = CollectionOfOne(OpaqueValue(42))
95+
expectEqual(0, c.startIndex)
96+
expectEqual(1, c.endIndex)
97+
expectEqual(0..<1, c.indices)
98+
99+
checkRandomAccessCollection(
100+
[ OpaqueValue(42) ], c) { $0.value == $1.value }
101+
}
102+
103+
LazyTestSuite.test("CollectionOfOne/AssociatedTypes") {
104+
typealias Subject = CollectionOfOne<OpaqueValue<Int>>
105+
expectRandomAccessCollectionAssociatedTypes(
106+
collectionType: Subject.self,
107+
iteratorType: IteratorOverOne<OpaqueValue<Int>>.self,
108+
subSequenceType: MutableRandomAccessSlice<Subject>.self,
109+
indexType: Int.self,
110+
indexDistanceType: Int.self,
111+
indicesType: CountableRange<Int>.self)
112+
}
113+
114+
% for (name, operation, indices) in [
115+
% ('index(after:)', '_ = c.index(after: i)', '-2, -1, 1, 2'),
116+
% ('index(before:)', '_ = c.index(before: i)', '-1, 0, 2'),
117+
% ('subscript(Index)/Get', '_ = c[i]', '-2, -1, 1, 2'),
118+
% ('subscript(Index)/Set', 'c[i] = OpaqueValue(42)', '-2, -1, 1, 2'),
119+
% ]:
120+
LazyTestSuite.test("CollectionOfOne/${name}")
121+
.forEach(in: [${indices}]) {
122+
i in
123+
124+
var c = CollectionOfOne<OpaqueValue<Int>>(OpaqueValue(42))
125+
expectCrashLater()
126+
${operation}
127+
}
128+
% end
129+
130+
LazyTestSuite.test("CollectionOfOne/subscript(Index)/Get/Set/Empty/NoTrap") {
131+
var c = CollectionOfOne<OpaqueValue<Int>>(OpaqueValue(42))
132+
c[0] = OpaqueValue(4242)
133+
expectEqual(4242, c[0].value)
134+
expectEqualSequence([OpaqueValue(4242)], c) { $0.value == $1.value }
135+
}
136+
137+
% for (name, operation) in [
138+
% ('subscript(Range<Index>)/Get', '_ = c[r]'),
139+
% ('subscript(Range<Index>)/Set', 'c[r] = slice'),
140+
% ]:
141+
LazyTestSuite.test("CollectionOfOne/${name}/Trap")
142+
.forEach(in: [
143+
-1 ..< -1, -1..<0, -1..<1, 1..<2, 2..<2,
144+
] as [Range<Int>]) {
145+
r in
146+
var c = CollectionOfOne<OpaqueValue<Int>>(OpaqueValue(42))
147+
let slice = r.count == 0 ? c[0..<0] : c[0..<1]
148+
expectCrashLater()
149+
${operation}
150+
}
151+
% end
152+
153+
LazyTestSuite.test("CollectionOfOne/subscript(Range<Index>)/Set/DifferentLength/Trap")
154+
.forEach(in: [ 0..<0, 0..<1, 1..<1 ] as [Range<Int>]) {
155+
r in
156+
var c = CollectionOfOne<OpaqueValue<Int>>(OpaqueValue(42))
157+
let slice = r.count == 0 ? c[0..<1] : c[0..<0]
158+
expectCrashLater()
159+
c[r] = slice
160+
}
161+
162+
LazyTestSuite.test("CollectionOfOne/subscript(Range<Index>)/Get/Set/Empty/NoTrap") {
163+
var c = CollectionOfOne<OpaqueValue<Int>>(OpaqueValue(42))
164+
let slice0 = c[0..<0]
165+
let slice1 = c[1..<1]
166+
checkRandomAccessCollection([], slice0) { $0.value == $1.value }
167+
checkRandomAccessCollection([], slice1) { $0.value == $1.value }
168+
c[0..<0] = slice0
169+
c[0..<0] = slice1
170+
c[1..<1] = slice0
171+
c[1..<1] = slice1
172+
expectEqualSequence([OpaqueValue(42)], c) { $0.value == $1.value }
173+
}
174+
175+
LazyTestSuite.test("CollectionOfOne/{CustomDebugStringConvertible,CustomReflectable}") {
176+
let c = CollectionOfOne(CustomPrintableValue(42))
177+
expectPrinted("CollectionOfOne((value: 42).debugDescription)", c)
178+
expectDebugPrinted("CollectionOfOne((value: 42).debugDescription)", c)
179+
expectDumped(
180+
"▿ CollectionOfOne((value: 42).debugDescription)\n" +
181+
" ▿ element: (value: 42).debugDescription\n" +
182+
" - value: 42\n" +
183+
" - identity: 0\n",
184+
c)
185+
}
186+
101187
//===----------------------------------------------------------------------===//
102188
// EmptyCollection
103189
//===----------------------------------------------------------------------===//
@@ -118,6 +204,15 @@ LazyTestSuite.test("EmptyCollection") {
118204
checkRandomAccessCollection([], c) { $0.value == $1.value }
119205
}
120206

207+
LazyTestSuite.test("EmptyCollection/CustomReflectable") {
208+
let c = EmptyCollection<OpaqueValue<Int>>()
209+
expectPrinted("EmptyCollection<OpaqueValue<Int>>()", c)
210+
expectDebugPrinted("Swift.EmptyCollection<StdlibUnittest.OpaqueValue<Swift.Int>>()", c)
211+
expectDumped(
212+
"- Swift.EmptyCollection<StdlibUnittest.OpaqueValue<Swift.Int>>\n",
213+
c)
214+
}
215+
121216
LazyTestSuite.test("EmptyCollection/Equatable") {
122217
let instances = [ EmptyCollection<OpaqueValue<Int>>() ]
123218
checkEquatable(instances, oracle: { $0 == $1 })

0 commit comments

Comments
 (0)