Skip to content

Commit 87db90c

Browse files
committed
stdlib: Address StrictMemorySafety warnings in Dictionary related code.
1 parent 322443d commit 87db90c

File tree

8 files changed

+114
-104
lines changed

8 files changed

+114
-104
lines changed

stdlib/public/core/Bitset.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ extension _UnsafeBitset: @unsafe Sequence {
150150
return unsafe Iterator(self)
151151
}
152152

153+
@unsafe
153154
@usableFromInline
154155
@frozen
155156
internal struct Iterator: IteratorProtocol {

stdlib/public/core/Dictionary.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ extension Dictionary: ExpressibleByDictionaryLiteral {
838838
for (key, value) in elements {
839839
let (bucket, found) = native.find(key)
840840
_precondition(!found, "Dictionary literal contains duplicate keys")
841-
native._insert(at: bucket, key: key, value: value)
841+
unsafe native._insert(at: bucket, key: key, value: value)
842842
}
843843
self.init(_native: native)
844844
}
@@ -904,11 +904,11 @@ extension Dictionary {
904904
}
905905
@inline(__always)
906906
_modify {
907-
let (bucket, found) = _variant.mutatingFind(key)
907+
let (bucket, found) = unsafe _variant.mutatingFind(key)
908908
let native = _variant.asNative
909909
if !found {
910910
let value = defaultValue()
911-
native._insert(at: bucket, key: key, value: value)
911+
unsafe native._insert(at: bucket, key: key, value: value)
912912
}
913913
let address = unsafe native._values + bucket.offset
914914
defer { _fixLifetime(self) }
@@ -1376,7 +1376,7 @@ extension Dictionary {
13761376
if
13771377
lhs._variant.isNative,
13781378
rhs._variant.isNative,
1379-
lhs._variant.asNative._storage === rhs._variant.asNative._storage
1379+
unsafe (lhs._variant.asNative._storage === rhs._variant.asNative._storage)
13801380
{
13811381
return true
13821382
}
@@ -1388,7 +1388,7 @@ extension Dictionary {
13881388
return true
13891389
}
13901390
#else
1391-
if lhs._variant.asNative._storage === rhs._variant.asNative._storage {
1391+
if unsafe (lhs._variant.asNative._storage === rhs._variant.asNative._storage) {
13921392
return true
13931393
}
13941394
#endif
@@ -1458,7 +1458,7 @@ extension Dictionary {
14581458
}
14591459
_modify {
14601460
let native = _variant.ensureUniqueNative()
1461-
let bucket = native.validatedBucket(for: position)
1461+
let bucket = unsafe native.validatedBucket(for: position)
14621462
let address = unsafe native._values + bucket.offset
14631463
defer { _fixLifetime(self) }
14641464
yield unsafe &address.pointee
@@ -1491,9 +1491,9 @@ extension Dictionary {
14911491
#endif
14921492
let isUnique = _variant.isUniquelyReferenced()
14931493
let native = _variant.asNative
1494-
let a = native.validatedBucket(for: i)
1495-
let b = native.validatedBucket(for: j)
1496-
_variant.asNative.swapValuesAt(a, b, isUnique: isUnique)
1494+
let a = unsafe native.validatedBucket(for: i)
1495+
let b = unsafe native.validatedBucket(for: j)
1496+
unsafe _variant.asNative.swapValuesAt(a, b, isUnique: isUnique)
14971497
}
14981498
}
14991499
}
@@ -1793,7 +1793,7 @@ extension Dictionary {
17931793
@inlinable
17941794
@inline(__always)
17951795
internal init(_native index: _HashTable.Index) {
1796-
self.init(_variant: .native(index))
1796+
unsafe self.init(_variant: .native(index))
17971797
}
17981798

17991799
#if _runtime(_ObjC)
@@ -1876,7 +1876,7 @@ extension Dictionary.Index {
18761876
"Attempting to access Dictionary elements using an invalid index")
18771877
}
18781878
let dummy = unsafe _HashTable.Index(bucket: _HashTable.Bucket(offset: 0), age: 0)
1879-
_variant = .native(dummy)
1879+
_variant = unsafe .native(dummy)
18801880
defer { _variant = .cocoa(cocoa) }
18811881
yield &cocoa
18821882
}

stdlib/public/core/DictionaryBridging.swift

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ final internal class _SwiftDictionaryNSEnumerator<Key: Hashable, Value>
7171
_internalInvariant(_isBridgedVerbatimToObjectiveC(Key.self))
7272
_internalInvariant(_orphanedFoundationSubclassesReparented)
7373
self.base = base
74-
self.bridgedKeys = nil
75-
self.nextBucket = unsafe base.hashTable.startBucket
76-
self.endBucket = unsafe base.hashTable.endBucket
74+
unsafe self.bridgedKeys = nil
75+
unsafe self.nextBucket = base.hashTable.startBucket
76+
unsafe self.endBucket = base.hashTable.endBucket
7777
super.init()
7878
}
7979

@@ -82,28 +82,28 @@ final internal class _SwiftDictionaryNSEnumerator<Key: Hashable, Value>
8282
_internalInvariant(!_isBridgedVerbatimToObjectiveC(Key.self))
8383
_internalInvariant(_orphanedFoundationSubclassesReparented)
8484
self.base = deferred.native
85-
self.bridgedKeys = unsafe deferred.bridgeKeys()
86-
self.nextBucket = unsafe base.hashTable.startBucket
87-
self.endBucket = unsafe base.hashTable.endBucket
85+
unsafe self.bridgedKeys = deferred.bridgeKeys()
86+
unsafe self.nextBucket = base.hashTable.startBucket
87+
unsafe self.endBucket = base.hashTable.endBucket
8888
super.init()
8989
}
9090

9191
private func bridgedKey(at bucket: _HashTable.Bucket) -> AnyObject {
9292
unsafe _internalInvariant(base.hashTable.isOccupied(bucket))
93-
if let bridgedKeys = self.bridgedKeys {
93+
if let bridgedKeys = unsafe self.bridgedKeys {
9494
return unsafe bridgedKeys[bucket]
9595
}
96-
return _bridgeAnythingToObjectiveC(base.uncheckedKey(at: bucket))
96+
return unsafe _bridgeAnythingToObjectiveC(base.uncheckedKey(at: bucket))
9797
}
9898

9999
@objc
100100
internal func nextObject() -> AnyObject? {
101101
if unsafe nextBucket == endBucket {
102102
return nil
103103
}
104-
let bucket = nextBucket
105-
nextBucket = unsafe base.hashTable.occupiedBucket(after: nextBucket)
106-
return self.bridgedKey(at: bucket)
104+
let bucket = unsafe nextBucket
105+
unsafe nextBucket = base.hashTable.occupiedBucket(after: nextBucket)
106+
return unsafe self.bridgedKey(at: bucket)
107107
}
108108

109109
@objc(countByEnumeratingWithState:objects:count:)
@@ -128,7 +128,7 @@ final internal class _SwiftDictionaryNSEnumerator<Key: Hashable, Value>
128128
// enumeration, terminate it, and continue via NSEnumerator.
129129
let unmanagedObjects = unsafe _UnmanagedAnyObjectArray(objects)
130130
unsafe unmanagedObjects[0] = self.bridgedKey(at: nextBucket)
131-
nextBucket = unsafe base.hashTable.occupiedBucket(after: nextBucket)
131+
unsafe nextBucket = base.hashTable.occupiedBucket(after: nextBucket)
132132
unsafe state.pointee = theState
133133
return 1
134134
}
@@ -230,7 +230,8 @@ final internal class _SwiftDeferredNSDictionary<Key: Hashable, Value>
230230
owner: native._storage,
231231
hashTable: native.hashTable)
232232
for unsafe bucket in unsafe native.hashTable {
233-
let object = _bridgeAnythingToObjectiveC(native.uncheckedKey(at: bucket))
233+
let object = unsafe _bridgeAnythingToObjectiveC(
234+
native.uncheckedKey(at: bucket))
234235
unsafe bridged.initialize(at: bucket, to: object)
235236
}
236237

@@ -249,7 +250,7 @@ final internal class _SwiftDeferredNSDictionary<Key: Hashable, Value>
249250
owner: native._storage,
250251
hashTable: native.hashTable)
251252
for unsafe bucket in unsafe native.hashTable {
252-
let value = native.uncheckedValue(at: bucket)
253+
let value = unsafe native.uncheckedValue(at: bucket)
253254
let cocoaValue = _bridgeAnythingToObjectiveC(value)
254255
unsafe bridged.initialize(at: bucket, to: cocoaValue)
255256
}
@@ -274,7 +275,7 @@ final internal class _SwiftDeferredNSDictionary<Key: Hashable, Value>
274275
if let bridgedKeys = unsafe bridgedKeys {
275276
return unsafe bridgedKeys[bucket]
276277
}
277-
return _bridgeAnythingToObjectiveC(native.uncheckedKey(at: bucket))
278+
return unsafe _bridgeAnythingToObjectiveC(native.uncheckedKey(at: bucket))
278279
}
279280

280281
@inline(__always)
@@ -285,7 +286,7 @@ final internal class _SwiftDeferredNSDictionary<Key: Hashable, Value>
285286
if let bridgedValues = unsafe bridgedValues {
286287
return unsafe bridgedValues[bucket]
287288
}
288-
return _bridgeAnythingToObjectiveC(native.uncheckedValue(at: bucket))
289+
return unsafe _bridgeAnythingToObjectiveC(native.uncheckedValue(at: bucket))
289290
}
290291

291292
@objc(objectForKey:)
@@ -383,7 +384,7 @@ final internal class _SwiftDeferredNSDictionary<Key: Hashable, Value>
383384
count: Int
384385
) -> Int {
385386
defer { _fixLifetime(self) }
386-
let hashTable = native.hashTable
387+
let hashTable = unsafe native.hashTable
387388

388389
var theState = unsafe state.pointee
389390
if unsafe theState.state == 0 {
@@ -809,7 +810,7 @@ extension Dictionary {
809810
}
810811

811812
if let nativeStorage = unsafe s as? _DictionaryStorage<Key, Value> {
812-
return Dictionary(_native: _NativeDictionary(nativeStorage))
813+
return Dictionary(_native: unsafe _NativeDictionary(nativeStorage))
813814
}
814815

815816
if unsafe s === __RawDictionaryStorage.empty {

stdlib/public/core/DictionaryBuilder.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ extension Dictionary {
8484
_ values: UnsafeMutableBufferPointer<Value>
8585
) -> Int
8686
) {
87-
self.init(_native: _NativeDictionary(
87+
self.init(_native: unsafe _NativeDictionary(
8888
_unsafeUninitializedCapacity: capacity,
8989
allowingDuplicates: allowingDuplicates,
9090
initializingWith: initializer))
@@ -151,7 +151,7 @@ extension _NativeDictionary {
151151
unsafe _internalInvariant(b != bucket)
152152
_precondition(allowingDuplicates, "Duplicate keys found")
153153
// Discard duplicate entry.
154-
uncheckedDestroy(at: bucket)
154+
unsafe uncheckedDestroy(at: bucket)
155155
unsafe _storage._count -= 1
156156
unsafe bucket.offset -= 1
157157
continue
@@ -166,7 +166,7 @@ extension _NativeDictionary {
166166
if unsafe target > bucket {
167167
// The target is outside the unprocessed region. We can simply move the
168168
// entry, leaving behind an uninitialized bucket.
169-
moveEntry(from: bucket, to: target)
169+
unsafe moveEntry(from: bucket, to: target)
170170
// Restore invariants by lowering the region boundary.
171171
unsafe bucket.offset -= 1
172172
} else if unsafe target == bucket {
@@ -176,7 +176,7 @@ extension _NativeDictionary {
176176
// The target bucket is also in the unprocessed region. Swap the current
177177
// item into place, then try again with the swapped-in value, so that we
178178
// don't lose it.
179-
swapEntry(target, with: bucket)
179+
unsafe swapEntry(target, with: bucket)
180180
}
181181
}
182182
// When there are no more unprocessed entries, we're left with a valid

stdlib/public/core/DictionaryStorage.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,12 +232,14 @@ extension __RawDictionaryStorage {
232232
return unsafe keys[bucket.offset]
233233
}
234234

235+
@safe
235236
@_alwaysEmitIntoClient
236237
@inline(never)
237238
internal final func find<Key: Hashable>(_ key: Key) -> (bucket: _HashTable.Bucket, found: Bool) {
238239
return unsafe find(key, hashValue: key._rawHashValue(seed: _seed))
239240
}
240241

242+
@safe
241243
@_alwaysEmitIntoClient
242244
@inline(never)
243245
internal final func find<Key: Hashable>(_ key: Key, hashValue: Int) -> (bucket: _HashTable.Bucket, found: Bool) {
@@ -298,7 +300,7 @@ final internal class _DictionaryStorage<Key: Hashable, Value>
298300
}
299301

300302
internal var asNative: _NativeDictionary<Key, Value> {
301-
return _NativeDictionary(self)
303+
return unsafe _NativeDictionary(self)
302304
}
303305

304306
#if _runtime(_ObjC)

stdlib/public/core/DictionaryVariant.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ extension Dictionary {
4141
@inlinable
4242
@inline(__always)
4343
init(native: __owned _NativeDictionary<Key, Value>) {
44-
self.object = unsafe _BridgeStorage(native: native._storage)
44+
unsafe self.object = _BridgeStorage(native: native._storage)
4545
}
4646

4747
@inlinable
4848
@inline(__always)
4949
init(dummy: Void) {
5050
#if _pointerBitWidth(_64) && !$Embedded
51-
self.object = unsafe _BridgeStorage(taggedPayload: 0)
51+
unsafe self.object = _BridgeStorage(taggedPayload: 0)
5252
#elseif _pointerBitWidth(_32) || $Embedded
5353
self.init(native: _NativeDictionary())
5454
#else
@@ -60,7 +60,7 @@ extension Dictionary {
6060
@inlinable
6161
@inline(__always)
6262
init(cocoa: __owned __CocoaDictionary) {
63-
self.object = unsafe _BridgeStorage(objC: cocoa.object)
63+
unsafe self.object = _BridgeStorage(objC: cocoa.object)
6464
}
6565
#endif
6666
}
@@ -83,7 +83,7 @@ extension Dictionary._Variant {
8383
@usableFromInline @_transparent
8484
internal var isNative: Bool {
8585
if guaranteedNative { return true }
86-
return object.isUnflaggedNative
86+
return unsafe object.isUnflaggedNative
8787
}
8888
#endif
8989

@@ -98,7 +98,7 @@ extension Dictionary._Variant {
9898
_modify {
9999
var native = unsafe _NativeDictionary<Key, Value>(object.unflaggedNativeInstance)
100100
self = .init(dummy: ())
101-
defer { object = unsafe .init(native: native._storage) }
101+
defer { unsafe object = .init(native: native._storage) }
102102
yield &native
103103
}
104104
}
@@ -390,8 +390,8 @@ extension Dictionary._Variant {
390390
// FIXME(performance): fuse data migration and element deletion into one
391391
// operation.
392392
let native = ensureUniqueNative()
393-
let bucket = native.validatedBucket(for: index)
394-
return asNative.uncheckedRemove(at: bucket, isUnique: true)
393+
let bucket = unsafe native.validatedBucket(for: index)
394+
return unsafe asNative.uncheckedRemove(at: bucket, isUnique: true)
395395
}
396396

397397
@inlinable
@@ -404,15 +404,15 @@ extension Dictionary._Variant {
404404
var native = _NativeDictionary<Key, Value>(cocoa)
405405
let (bucket, found) = native.find(key)
406406
_precondition(found, "Bridging did not preserve equality")
407-
let old = native.uncheckedRemove(at: bucket, isUnique: true).value
407+
let old = unsafe native.uncheckedRemove(at: bucket, isUnique: true).value
408408
self = .init(native: native)
409409
return old
410410
}
411411
#endif
412412
let (bucket, found) = asNative.find(key)
413413
guard found else { return nil }
414414
let isUnique = isUniquelyReferenced()
415-
return asNative.uncheckedRemove(at: bucket, isUnique: isUnique).value
415+
return unsafe asNative.uncheckedRemove(at: bucket, isUnique: isUnique).value
416416
}
417417

418418
@inlinable

stdlib/public/core/HashTable.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ extension _HashTable.Bucket: Comparable {
186186
}
187187

188188
extension _HashTable {
189+
@unsafe
189190
@usableFromInline
190191
@frozen
191192
internal struct Index {
@@ -231,6 +232,7 @@ extension _HashTable.Index: Comparable {
231232
}
232233

233234
extension _HashTable: @unsafe Sequence {
235+
@unsafe
234236
@usableFromInline
235237
@frozen
236238
internal struct Iterator: @unsafe IteratorProtocol {
@@ -280,6 +282,7 @@ extension _HashTable: @unsafe Sequence {
280282
extension _HashTable.Iterator: Sendable {}
281283

282284
extension _HashTable {
285+
@safe
283286
@inlinable
284287
@inline(__always)
285288
internal func isValid(_ bucket: Bucket) -> Bool {
@@ -289,7 +292,7 @@ extension _HashTable {
289292
@inlinable
290293
@inline(__always)
291294
internal func _isOccupied(_ bucket: Bucket) -> Bool {
292-
unsafe _internalInvariant(isValid(bucket))
295+
_internalInvariant(isValid(bucket))
293296
return unsafe words[bucket.word].uncheckedContains(bucket.bit)
294297
}
295298

@@ -322,7 +325,7 @@ extension _HashTable {
322325

323326
@inlinable
324327
internal func occupiedBucket(after bucket: Bucket) -> Bucket {
325-
unsafe _internalInvariant(isValid(bucket))
328+
_internalInvariant(isValid(bucket))
326329
let word = unsafe bucket.word
327330
if let bit = unsafe words[word].intersecting(elementsAbove: bucket.bit).minimum {
328331
return unsafe Bucket(word: word, bit: bit)
@@ -364,7 +367,7 @@ extension _HashTable {
364367
extension _HashTable {
365368
@inlinable
366369
internal func previousHole(before bucket: Bucket) -> Bucket {
367-
unsafe _internalInvariant(isValid(bucket))
370+
_internalInvariant(isValid(bucket))
368371
// Note that if we have only a single partial word, its out-of-bounds bits
369372
// are guaranteed to be all set, so the formula below gives correct results.
370373
var word = unsafe bucket.word
@@ -392,7 +395,7 @@ extension _HashTable {
392395

393396
@inlinable
394397
internal func nextHole(atOrAfter bucket: Bucket) -> Bucket {
395-
unsafe _internalInvariant(isValid(bucket))
398+
_internalInvariant(isValid(bucket))
396399
// Note that if we have only a single partial word, its out-of-bounds bits
397400
// are guaranteed to be all set, so the formula below gives correct results.
398401
var word = unsafe bucket.word

0 commit comments

Comments
 (0)