Skip to content

Commit 286fedb

Browse files
committed
Merge branch 'release/1.0'
2 parents 6eeae80 + 4825482 commit 286fedb

File tree

11 files changed

+124
-103
lines changed

11 files changed

+124
-103
lines changed

Documentation/OrderedSet.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ let b: OrderedSet = [3, 2, 1, 0]
101101
a == b // false
102102
a.unordered == b.unordered // true
103103

104-
func frobnicate<S: OrderedSet>(_ set: S) { ... }
104+
func frobnicate<S: SetAlgebra>(_ set: S) { ... }
105105
frobnicate(a) // error: `OrderedSet<String>` does not conform to `SetAlgebra`
106106
frobnicate(a.unordered) // OK
107107
```

Sources/DequeModule/Deque+Collection.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ extension Deque: RangeReplaceableCollection {
672672
}
673673

674674
let underestimatedCount = newElements.underestimatedCount
675-
reserveCapacity(count + underestimatedCount)
675+
_storage.ensureUnique(minimumCapacity: count + underestimatedCount)
676676
var it: S.Iterator = _storage.update { target in
677677
let gaps = target.availableSegments()
678678
let (it, copied) = gaps.initialize(fromSequencePrefix: newElements)
@@ -713,7 +713,7 @@ extension Deque: RangeReplaceableCollection {
713713

714714
let c = newElements.count
715715
guard c > 0 else { return }
716-
reserveCapacity(count + c)
716+
_storage.ensureUnique(minimumCapacity: count + c)
717717
_storage.update { target in
718718
let gaps = target.availableSegments().prefix(c)
719719
gaps.initialize(from: newElements)

Sources/OrderedCollections/OrderedSet/OrderedSet+Insertions.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ extension OrderedSet {
129129
return
130130
}
131131

132+
_ensureUnique()
132133
_table!.update { hashTable in
133134
assert(!hashTable.isOccupied(bucket))
134135
hashTable.adjustContents(preparingForInsertionOfElementAtOffset: index, in: _elements)

Sources/OrderedCollections/OrderedSet/OrderedSet.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
/// a == b // false
9090
/// a.unordered == b.unordered // true
9191
///
92-
/// func frobnicate<S: OrderedSet>(_ set: S) { ... }
92+
/// func frobnicate<S: SetAlgebra>(_ set: S) { ... }
9393
/// frobnicate(a) // error: `OrderedSet<String>` does not conform to `SetAlgebra`
9494
/// frobnicate(a.unordered) // OK
9595
///

Sources/_CollectionsTestSupport/AssertionContexts/Combinatorics.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,12 @@ public func withSomeRanges<T: Strideable>(
132132
/// - Parameters:
133133
/// - `enabled`: if `false`, then no copies are made -- the values are passed to `body` with no processing.
134134
/// - `value`: The collection value that is being tested.
135+
/// - `checker`: An optional function that is used to check the consistency of the hidden copy.
135136
/// - `body`: A closure performing a mutation on `value`.
136137
public func withHiddenCopies<S: Sequence, R>(
137138
if enabled: Bool,
138139
of value: inout S,
140+
checker: (S) -> Void = { _ in },
139141
file: StaticString = #file, line: UInt = #line,
140142
_ body: (inout S) throws -> R
141143
) rethrows -> R where S.Element: Equatable {
@@ -144,6 +146,7 @@ public func withHiddenCopies<S: Sequence, R>(
144146
let expected = Array(value)
145147
let result = try body(&value)
146148
expectEqualElements(copy, expected, file: file, line: line)
149+
checker(copy)
147150
return result
148151
}
149152

@@ -156,6 +159,7 @@ public func withHiddenCopies<S: Sequence, R>(
156159
/// - Parameters:
157160
/// - `enabled`: if `false`, then no copies are made -- the values are passed to `body` with no processing.
158161
/// - `value`: The collection value that is being tested.
162+
/// - `checker`: An optional function that is used to check the consistency of the hidden copy.
159163
/// - `body`: A closure performing a mutation on `value`.
160164
public func withHiddenCopies<
161165
S: Sequence,
@@ -165,6 +169,7 @@ public func withHiddenCopies<
165169
>(
166170
if enabled: Bool,
167171
of value: inout S,
172+
checker: (S) -> Void = { _ in },
168173
file: StaticString = #file, line: UInt = #line,
169174
_ body: (inout S) throws -> R
170175
) rethrows -> R where S.Element == (key: Key, value: Value) {
@@ -173,5 +178,6 @@ public func withHiddenCopies<
173178
let expected = Array(value)
174179
let result = try body(&value)
175180
expectEqualElements(copy, expected, file: file, line: line)
181+
checker(copy)
176182
return result
177183
}

Tests/OrderedCollectionsTests/OrderedDictionary/OrderedDictionary Tests.swift

Lines changed: 34 additions & 34 deletions
Large diffs are not rendered by default.

Tests/OrderedCollectionsTests/OrderedDictionary/OrderedDictionary+Elements Tests.swift

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
148148
withLifetimeTracking { tracker in
149149
var (d, reference) = tracker.orderedDictionary(keys: 0 ..< count)
150150
reference.swapAt(i, j)
151-
withHiddenCopies(if: isShared, of: &d) { d in
151+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
152152
d.elements.swapAt(i, j)
153153
expectEquivalentElements(
154154
d, reference,
@@ -172,7 +172,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
172172
var (d, reference) = tracker.orderedDictionary(
173173
keys: (0 ..< count).shuffled(using: &rng))
174174
let expectedPivot = reference.partition { $0.key.payload < count / 2 }
175-
withHiddenCopies(if: isShared, of: &d) { d in
175+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
176176
let actualPivot = d.elements.partition { $0.key.payload < count / 2 }
177177
expectEqual(actualPivot, expectedPivot)
178178
expectEqualElements(d, reference)
@@ -192,7 +192,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
192192
var (d, reference) = tracker.orderedDictionary(
193193
keys: (0 ..< count).shuffled(using: &rng))
194194
reference.sort(by: { $0.key < $1.key })
195-
withHiddenCopies(if: isShared, of: &d) { d in
195+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
196196
d.elements.sort()
197197
expectEqualElements(d, reference)
198198
}
@@ -211,7 +211,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
211211
var (d, reference) = tracker.orderedDictionary(
212212
keys: (0 ..< count).shuffled(using: &rng))
213213
reference.sort(by: { $0.key > $1.key })
214-
withHiddenCopies(if: isShared, of: &d) { d in
214+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
215215
d.elements.sort(by: { $0.key > $1.key })
216216
expectEqualElements(d, reference)
217217
}
@@ -229,7 +229,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
229229
uniqueKeys: 0 ..< count,
230230
values: 100 ..< 100 + count)
231231
var items = (0 ..< count).map { (key: $0, value: 100 + $0) }
232-
withHiddenCopies(if: isShared, of: &d) { d in
232+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
233233
expectEqualElements(d.elements, items)
234234

235235
var rng1 = RepeatableRandomNumberGenerator(seed: seed)
@@ -271,7 +271,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
271271
withEvery("isShared", in: [false, true]) { isShared in
272272
withLifetimeTracking { tracker in
273273
var (d, reference) = tracker.orderedDictionary(keys: 0 ..< count)
274-
withHiddenCopies(if: isShared, of: &d) { d in
274+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
275275
reference.reverse()
276276
d.elements.reverse()
277277
expectEqualElements(d, reference)
@@ -286,7 +286,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
286286
withEvery("isShared", in: [false, true]) { isShared in
287287
withLifetimeTracking { tracker in
288288
var (d, _) = tracker.orderedDictionary(keys: 0 ..< count)
289-
withHiddenCopies(if: isShared, of: &d) { d in
289+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
290290
d.elements.removeAll()
291291
expectEqual(d.keys.__unstable.scale, 0)
292292
expectEqualElements(d, [])
@@ -302,7 +302,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
302302
withLifetimeTracking { tracker in
303303
var (d, _) = tracker.orderedDictionary(keys: 0 ..< count)
304304
let origScale = d.keys.__unstable.scale
305-
withHiddenCopies(if: isShared, of: &d) { d in
305+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
306306
d.elements.removeAll(keepingCapacity: true)
307307
expectEqual(d.keys.__unstable.scale, origScale)
308308
expectEqualElements(d, [])
@@ -318,7 +318,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
318318
withEvery("isShared", in: [false, true]) { isShared in
319319
withLifetimeTracking { tracker in
320320
var (d, reference) = tracker.orderedDictionary(keys: 0 ..< count)
321-
withHiddenCopies(if: isShared, of: &d) { d in
321+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
322322
let actual = d.elements.remove(at: offset)
323323
let expected = reference.remove(at: offset)
324324
expectEqual(actual.key, expected.key)
@@ -337,7 +337,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
337337
withEvery("isShared", in: [false, true]) { isShared in
338338
withLifetimeTracking { tracker in
339339
var (d, reference) = tracker.orderedDictionary(keys: 0 ..< count)
340-
withHiddenCopies(if: isShared, of: &d) { d in
340+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
341341
d.elements.removeSubrange(range)
342342
reference.removeSubrange(range)
343343
expectEqualElements(d, reference)
@@ -370,7 +370,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
370370
withLifetimeTracking { tracker in
371371
var (d, reference) = tracker.orderedDictionary(keys: 0 ..< 30)
372372
withEvery("i", in: 0 ..< d.count) { i in
373-
withHiddenCopies(if: isShared, of: &d) { d in
373+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
374374
let actual = d.elements.removeLast()
375375
let expected = reference.removeLast()
376376
expectEqual(actual.key, expected.key)
@@ -387,7 +387,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
387387
withLifetimeTracking { tracker in
388388
var (d, reference) = tracker.orderedDictionary(keys: 0 ..< 30)
389389
withEvery("i", in: 0 ..< d.count) { i in
390-
withHiddenCopies(if: isShared, of: &d) { d in
390+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
391391
let actual = d.elements.removeFirst()
392392
let expected = reference.removeFirst()
393393
expectEqual(actual.key, expected.key)
@@ -405,7 +405,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
405405
withEvery("isShared", in: [false, true]) { isShared in
406406
withLifetimeTracking { tracker in
407407
var (d, reference) = tracker.orderedDictionary(keys: 0 ..< count)
408-
withHiddenCopies(if: isShared, of: &d) { d in
408+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
409409
d.elements.removeLast(suffix)
410410
reference.removeLast(suffix)
411411
expectEqualElements(d, reference)
@@ -422,7 +422,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
422422
withEvery("isShared", in: [false, true]) { isShared in
423423
withLifetimeTracking { tracker in
424424
var (d, reference) = tracker.orderedDictionary(keys: 0 ..< count)
425-
withHiddenCopies(if: isShared, of: &d) { d in
425+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
426426
d.elements.removeFirst(prefix)
427427
reference.removeFirst(prefix)
428428
expectEqualElements(d, reference)
@@ -439,7 +439,7 @@ class OrderedDictionaryElementsTests: CollectionTestCase {
439439
withEvery("isShared", in: [false, true]) { isShared in
440440
withLifetimeTracking { tracker in
441441
var (d, reference) = tracker.orderedDictionary(keys: 0 ..< count)
442-
withHiddenCopies(if: isShared, of: &d) { d in
442+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
443443
d.elements.removeAll(where: { !$0.key.payload.isMultiple(of: n) })
444444
reference.removeAll(where: { !$0.key.payload.isMultiple(of: n) })
445445
expectEqualElements(d, reference)

Tests/OrderedCollectionsTests/OrderedDictionary/OrderedDictionary+Values Tests.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class OrderedDictionaryValueTests: CollectionTestCase {
4141
withLifetimeTracking { tracker in
4242
var (d, reference) = tracker.orderedDictionary(keys: 0 ..< count)
4343
let replacement = tracker.instance(for: -1)
44-
withHiddenCopies(if: isShared, of: &d) { d in
44+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
4545
d.values[offset] = replacement
4646
reference[offset].value = replacement
4747
expectEqualElements(d.values, reference.map { $0.value })
@@ -95,7 +95,7 @@ class OrderedDictionaryValueTests: CollectionTestCase {
9595
let t = reference[i].value
9696
reference[i].value = reference[j].value
9797
reference[j].value = t
98-
withHiddenCopies(if: isShared, of: &d) { d in
98+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
9999
d.values.swapAt(i, j)
100100
expectEqualElements(d.values, reference.map { $0.value })
101101
expectEqual(d[reference[i].key], reference[i].value)
@@ -118,7 +118,7 @@ class OrderedDictionaryValueTests: CollectionTestCase {
118118
keys: (0 ..< count).shuffled(using: &rng))
119119
var values = reference.map { $0.value }
120120
let expectedPivot = values.partition { $0.payload < 100 + count / 2 }
121-
withHiddenCopies(if: isShared, of: &d) { d in
121+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d in
122122
let actualPivot = d.values.partition { $0.payload < 100 + count / 2 }
123123
expectEqual(actualPivot, expectedPivot)
124124
expectEqualElements(d.values, values)
@@ -139,7 +139,7 @@ class OrderedDictionaryValueTests: CollectionTestCase {
139139
var (d, reference) = tracker.orderedDictionary(keys: 0 ..< count)
140140
typealias R = [LifetimeTracked<Int>]
141141
let actual =
142-
withHiddenCopies(if: isShared, of: &d) { d -> R in
142+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d -> R in
143143
d.values.withUnsafeBufferPointer { buffer -> R in
144144
Array(buffer)
145145
}
@@ -158,7 +158,7 @@ class OrderedDictionaryValueTests: CollectionTestCase {
158158
let replacement = tracker.instances(for: (0 ..< count).map { -$0 })
159159
typealias R = [LifetimeTracked<Int>]
160160
let actual =
161-
withHiddenCopies(if: isShared, of: &d) { d -> R in
161+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d -> R in
162162
d.values.withUnsafeMutableBufferPointer { buffer -> R in
163163
let result = Array(buffer)
164164
expectEqual(buffer.count, replacement.count, trapping: true)
@@ -186,7 +186,7 @@ class OrderedDictionaryValueTests: CollectionTestCase {
186186
let replacement = tracker.instances(for: (0 ..< count).map { -$0 })
187187
typealias R = [LifetimeTracked<Int>]
188188
let actual =
189-
withHiddenCopies(if: isShared, of: &d) { d -> R? in
189+
withHiddenCopies(if: isShared, of: &d, checker: { $0._checkInvariants() }) { d -> R? in
190190
d.values.withContiguousMutableStorageIfAvailable { buffer -> R in
191191
let result = Array(buffer)
192192
expectEqual(buffer.count, replacement.count, trapping: true)

Tests/OrderedCollectionsTests/OrderedSet/OrderedSetTests.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ class OrderedSetTests: CollectionTestCase {
356356
let count = layout.count
357357
withEvery("offset", in: 0 ... count) { offset in
358358
var set = OrderedSet<Int>(layout: layout)
359-
withHiddenCopies(if: isShared, of: &set) { set in
359+
withHiddenCopies(if: isShared, of: &set, checker: { $0._checkInvariants() }) { set in
360360
let i = set.index(set.startIndex, offsetBy: offset)
361361
let (inserted, index) = set.insert(count, at: i)
362362
expectTrue(inserted)
@@ -511,7 +511,7 @@ class OrderedSetTests: CollectionTestCase {
511511
let count = layout.count
512512
withEvery("a", in: 0 ..< count) { a in
513513
var set = OrderedSet(layout: layout)
514-
withHiddenCopies(if: isShared, of: &set) { set in
514+
withHiddenCopies(if: isShared, of: &set, checker: { $0._checkInvariants() }) { set in
515515
let b = count - a - 1
516516
let ai = set._index(at: a)
517517
let bi = set._index(at: b)
@@ -535,7 +535,7 @@ class OrderedSetTests: CollectionTestCase {
535535
withEvery("isShared", in: [false, true]) { isShared in
536536
let count = layout.count
537537
var set = OrderedSet(layout: layout)
538-
withHiddenCopies(if: isShared, of: &set) { set in
538+
withHiddenCopies(if: isShared, of: &set, checker: { $0._checkInvariants() }) { set in
539539
let pivot = set.partition(by: { $0.isMultiple(of: 2) })
540540
withEvery("item", in: 0 ..< count) { item in
541541
expectNotNil(set.firstIndex(of: item)) { index in
@@ -559,7 +559,7 @@ class OrderedSetTests: CollectionTestCase {
559559
withEvery("isShared", in: [false, true]) { isShared in
560560
let count = layout.count
561561
var set = OrderedSet(layout: layout)
562-
withHiddenCopies(if: isShared, of: &set) { set in
562+
withHiddenCopies(if: isShared, of: &set, checker: { $0._checkInvariants() }) { set in
563563
do {
564564
let pivot = set.partition(by: { _ in false })
565565
expectEqual(pivot, set.endIndex)
@@ -585,7 +585,7 @@ class OrderedSetTests: CollectionTestCase {
585585
var rng = RepeatableRandomNumberGenerator(seed: seed)
586586
let contents = (0 ..< count).shuffled(using: &rng)
587587
var set = OrderedSet(layout: layout, contents: contents)
588-
withHiddenCopies(if: isShared, of: &set) { set in
588+
withHiddenCopies(if: isShared, of: &set, checker: { $0._checkInvariants() }) { set in
589589
set.sort()
590590
expectEqualElements(set, 0 ..< count)
591591

@@ -605,7 +605,7 @@ class OrderedSetTests: CollectionTestCase {
605605
let count = layout.count
606606
var contents = Array(0 ..< count)
607607
var set = OrderedSet(layout: layout, contents: 0 ..< count)
608-
withHiddenCopies(if: isShared, of: &set) { set in
608+
withHiddenCopies(if: isShared, of: &set, checker: { $0._checkInvariants() }) { set in
609609
var rng1 = RepeatableRandomNumberGenerator(seed: seed)
610610
contents.shuffle(using: &rng1)
611611

@@ -637,7 +637,7 @@ class OrderedSetTests: CollectionTestCase {
637637
let count = layout.count
638638
var contents = Array(0 ..< count)
639639
var set = OrderedSet(layout: layout, contents: 0 ..< count)
640-
withHiddenCopies(if: isShared, of: &set) { set in
640+
withHiddenCopies(if: isShared, of: &set, checker: { $0._checkInvariants() }) { set in
641641
contents.reverse()
642642
set.reverse()
643643
expectEqualElements(set, contents)
@@ -651,7 +651,7 @@ class OrderedSetTests: CollectionTestCase {
651651
withEvery("offset", in: 0 ..< layout.count) { offset in
652652
withEvery("isShared", in: [false, true]) { isShared in
653653
var set = OrderedSet(layout: layout)
654-
withHiddenCopies(if: isShared, of: &set) { set in
654+
withHiddenCopies(if: isShared, of: &set, checker: { $0._checkInvariants() }) { set in
655655
let count = layout.count
656656
let index = set._index(at: offset)
657657
let old = set.remove(at: index)
@@ -698,7 +698,7 @@ class OrderedSetTests: CollectionTestCase {
698698
withEvery("item", in: 0 ..< layout.count) { item in
699699
withEvery("isShared", in: [false, true]) { isShared in
700700
var set = OrderedSet(layout: layout)
701-
withHiddenCopies(if: isShared, of: &set) { set in
701+
withHiddenCopies(if: isShared, of: &set, checker: { $0._checkInvariants() }) { set in
702702
let count = layout.count
703703
let old = set.remove(item)
704704
expectEqual(old, item)
@@ -738,7 +738,7 @@ class OrderedSetTests: CollectionTestCase {
738738
var set = OrderedSet(layout: layout)
739739
let low = offsetRange.lowerBound
740740
let high = offsetRange.upperBound
741-
withHiddenCopies(if: isShared, of: &set) { set in
741+
withHiddenCopies(if: isShared, of: &set, checker: { $0._checkInvariants() }) { set in
742742
let count = layout.count
743743
let removedRange = set._indexRange(at: low ..< high)
744744
set.removeSubrange(removedRange)

0 commit comments

Comments
 (0)