Skip to content

Commit 34bda52

Browse files
authored
Merge pull request swiftlang#14305 from lorentey/rdar/36619317-4.1
[4.1][stdlib] Set, Dictionary: Take the max load factor into account in .init(minimumCapacity:)
2 parents 4cb7e7f + 9fc01b7 commit 34bda52

File tree

3 files changed

+74
-13
lines changed

3 files changed

+74
-13
lines changed

stdlib/public/core/HashedCollections.swift.gyb

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -477,9 +477,12 @@ extension Set {
477477
/// buffer.
478478
@_inlineable // FIXME(sil-serialize-all)
479479
public init(minimumCapacity: Int) {
480+
let reservedCapacity = _NativeBuffer.minimumCapacity(
481+
minimumCount: minimumCapacity,
482+
maxLoadFactorInverse: _hashContainerDefaultMaxLoadFactorInverse)
480483
_variantBuffer =
481484
_VariantBuffer.native(
482-
_NativeBuffer(minimumCapacity: minimumCapacity))
485+
_NativeBuffer(minimumCapacity: reservedCapacity))
483486
}
484487

485488
/// Private initializer.
@@ -1751,8 +1754,11 @@ public struct Dictionary<Key : Hashable, Value> {
17511754
/// allocate buffer for in the new dictionary.
17521755
@_inlineable // FIXME(sil-serialize-all)
17531756
public init(minimumCapacity: Int) {
1757+
let reservedCapacity = _NativeBuffer.minimumCapacity(
1758+
minimumCount: minimumCapacity,
1759+
maxLoadFactorInverse: _hashContainerDefaultMaxLoadFactorInverse)
17541760
_variantBuffer =
1755-
.native(_NativeBuffer(minimumCapacity: minimumCapacity))
1761+
.native(_NativeBuffer(minimumCapacity: reservedCapacity))
17561762
}
17571763

17581764
/// Creates a new dictionary from the key-value pairs in the given sequence.
@@ -4027,7 +4033,7 @@ extension _Native${Self}Buffer
40274033
maxLoadFactorInverse: Double
40284034
) -> Int {
40294035
// `minimumCount + 1` below ensures that we don't fill in the last hole
4030-
return max(Int(Double(minimumCount) * maxLoadFactorInverse),
4036+
return max(Int((Double(minimumCount) * maxLoadFactorInverse).rounded(.up)),
40314037
minimumCount + 1)
40324038
}
40334039

@@ -6402,11 +6408,7 @@ public struct _${Self}Builder<${TypeParametersDecl}> {
64026408

64036409
@_inlineable // FIXME(sil-serialize-all)
64046410
public init(count: Int) {
6405-
let requiredCapacity =
6406-
_Native${Self}Buffer<${TypeParameters}>.minimumCapacity(
6407-
minimumCount: count,
6408-
maxLoadFactorInverse: _hashContainerDefaultMaxLoadFactorInverse)
6409-
_result = ${Self}<${TypeParameters}>(minimumCapacity: requiredCapacity)
6411+
_result = ${Self}<${TypeParameters}>(minimumCapacity: count)
64106412
_nativeBuffer = _result._variantBuffer.asNative
64116413
_requestedCount = count
64126414
_actualCount = 0
@@ -6505,6 +6507,7 @@ extension ${Self} {
65056507
@_inlineable // FIXME(sil-serialize-all)
65066508
public mutating func reserveCapacity(_ minimumCapacity: Int) {
65076509
_variantBuffer.reserveCapacity(minimumCapacity)
6510+
_sanityCheck(self.capacity >= minimumCapacity)
65086511
}
65096512
}
65106513

validation-test/stdlib/Dictionary.swift

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,29 @@ DictionaryTestSuite.test("mapValues(_:)") {
17231723
}
17241724
}
17251725

1726+
DictionaryTestSuite.test("capacity/init(minimumCapacity:)") {
1727+
let d0 = Dictionary<String, Int>(minimumCapacity: 0)
1728+
expectGE(d0.capacity, 0)
1729+
1730+
let d1 = Dictionary<String, Int>(minimumCapacity: 1)
1731+
expectGE(d1.capacity, 1)
1732+
1733+
let d3 = Dictionary<String, Int>(minimumCapacity: 3)
1734+
expectGE(d3.capacity, 3)
1735+
1736+
let d4 = Dictionary<String, Int>(minimumCapacity: 4)
1737+
expectGE(d4.capacity, 4)
1738+
1739+
let d10 = Dictionary<String, Int>(minimumCapacity: 10)
1740+
expectGE(d10.capacity, 10)
1741+
1742+
let d100 = Dictionary<String, Int>(minimumCapacity: 100)
1743+
expectGE(d100.capacity, 100)
1744+
1745+
let d1024 = Dictionary<String, Int>(minimumCapacity: 1024)
1746+
expectGE(d1024.capacity, 1024)
1747+
}
1748+
17261749
DictionaryTestSuite.test("capacity/reserveCapacity(_:)") {
17271750
var d1 = [10: 1010, 20: 1020, 30: 1030]
17281751
expectEqual(3, d1.capacity)
@@ -2314,8 +2337,12 @@ DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.SubscriptWithKey") {
23142337

23152338
// Insert a new key-value pair.
23162339
d[TestBridgedKeyTy(40)] = TestBridgedValueTy(2040)
2340+
23172341
var identity2 = d._rawIdentifier()
2318-
assert(identity1 != identity2)
2342+
// Storage identity may or may not change depending on allocation behavior.
2343+
// (d is eagerly bridged to a regular uniquely referenced native Dictionary.)
2344+
//assert(identity1 != identity2)
2345+
23192346
assert(isNativeDictionary(d))
23202347
assert(d.count == 4)
23212348

@@ -2403,7 +2430,9 @@ DictionaryTestSuite.test("BridgedFromObjC.Nonverbatim.UpdateValueForKey") {
24032430
d.updateValue(TestBridgedValueTy(2040), forKey: TestBridgedKeyTy(40))
24042431
assert(oldValue == nil)
24052432
var identity2 = d._rawIdentifier()
2406-
assert(identity1 != identity2)
2433+
// Storage identity may or may not change depending on allocation behavior.
2434+
// (d is eagerly bridged to a regular uniquely referenced native Dictionary.)
2435+
//assert(identity1 != identity2)
24072436
assert(isNativeDictionary(d))
24082437
assert(d.count == 4)
24092438

validation-test/stdlib/Set.swift

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,7 +1418,10 @@ SetTestSuite.test("BridgedFromObjC.Nonverbatim.Insert") {
14181418
s.insert(TestObjCKeyTy(2040) as TestBridgedKeyTy)
14191419

14201420
var identity2 = s._rawIdentifier()
1421-
expectNotEqual(identity1, identity2)
1421+
// Storage identity may or may not change depending on allocation behavior.
1422+
// (s is eagerly bridged to a regular uniquely referenced native Set.)
1423+
//expectNotEqual(identity1, identity2)
1424+
14221425
expectTrue(isNativeSet(s))
14231426
expectEqual(4, s.count)
14241427

@@ -1572,10 +1575,13 @@ SetTestSuite.test("BridgedFromObjC.Nonverbatim.Contains") {
15721575

15731576
expectEqual(identity1, s._rawIdentifier())
15741577

1575-
// Inserting an item should now create storage unique from the bridged set.
15761578
s.insert(TestBridgedKeyTy(4040))
15771579
var identity2 = s._rawIdentifier()
1578-
expectNotEqual(identity1, identity2)
1580+
1581+
// Storage identity may or may not change depending on allocation behavior.
1582+
// (s is eagerly bridged to a regular uniquely referenced native Set.)
1583+
//expectNotEqual(identity1, identity2)
1584+
15791585
expectTrue(isNativeSet(s))
15801586
expectEqual(4, s.count)
15811587

@@ -3155,6 +3161,29 @@ SetTestSuite.test("first") {
31553161
expectNil(emptySet.first)
31563162
}
31573163

3164+
SetTestSuite.test("capacity/init(minimumCapacity:)") {
3165+
let s0 = Set<String>(minimumCapacity: 0)
3166+
expectGE(s0.capacity, 0)
3167+
3168+
let s1 = Set<String>(minimumCapacity: 1)
3169+
expectGE(s1.capacity, 1)
3170+
3171+
let s3 = Set<String>(minimumCapacity: 3)
3172+
expectGE(s3.capacity, 3)
3173+
3174+
let s4 = Set<String>(minimumCapacity: 4)
3175+
expectGE(s4.capacity, 4)
3176+
3177+
let s10 = Set<String>(minimumCapacity: 10)
3178+
expectGE(s10.capacity, 10)
3179+
3180+
let s100 = Set<String>(minimumCapacity: 100)
3181+
expectGE(s100.capacity, 100)
3182+
3183+
let s1024 = Set<String>(minimumCapacity: 1024)
3184+
expectGE(s1024.capacity, 1024)
3185+
}
3186+
31583187
SetTestSuite.test("capacity/reserveCapacity(_:)") {
31593188
var s1: Set = [10, 20, 30]
31603189
expectEqual(3, s1.capacity)

0 commit comments

Comments
 (0)