Skip to content

Commit 5fdd0c7

Browse files
author
Alexis Beingessner
committed
revert _CocoaDictionaryBuffer indexing design
The use of a lazy var crashes the swift module (de)serializer.
1 parent 982a57f commit 5fdd0c7

File tree

1 file changed

+77
-39
lines changed

1 file changed

+77
-39
lines changed

stdlib/public/core/HashedCollections.swift.gyb

Lines changed: 77 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3749,12 +3749,9 @@ final internal class _SwiftDeferredNS${Self}<${TypeParametersDecl}> { }
37493749
#endif
37503750

37513751
#if _runtime(_ObjC)
3752-
3753-
// FIXME: this should really be a struct but can't because of the lazy allKeys.
3754-
// (but it might be removed with eager bridging, so this is "fine" for now)
37553752
@_versioned
37563753
@_fixed_layout
3757-
internal final class _Cocoa${Self}Buffer : _HashBuffer {
3754+
internal struct _Cocoa${Self}Buffer : _HashBuffer {
37583755
@_versioned
37593756
internal var cocoa${Self}: _NS${Self}
37603757

@@ -3765,31 +3762,22 @@ internal final class _Cocoa${Self}Buffer : _HashBuffer {
37653762
internal typealias Key = AnyObject
37663763
internal typealias Value = AnyObject
37673764

3768-
internal lazy var allKeys : _Box<_HeapBuffer<Int, AnyObject>> = {
3769-
return _Box(_stdlib_NS${Self}_all${'Objects' if Self == 'Set' else 'Keys'}(self.cocoa${Self}))
3770-
}()
3771-
37723765
internal var startIndex: Index {
3773-
return Index(value: 0)
3766+
return Index(cocoa${Self}, startIndex: ())
37743767
}
37753768

37763769
internal var endIndex: Index {
3777-
return Index(value: allKeys._value.value)
3770+
return Index(cocoa${Self}, endIndex: ())
37783771
}
37793772

3780-
// Assumption: we rely on NS${Self}.getObjects when being
3781-
// repeatedly called on the same NS${Self}, returning items in the same
3782-
// order every time.
37833773
@_versioned
37843774
internal func index(after i: Index) -> Index {
3785-
_precondition(
3786-
i.currentKeyIndex < allKeys._value.value, "cannot increment endIndex")
3787-
return _Cocoa${Self}Index(value: i.currentKeyIndex + 1)
3775+
return i.successor()
37883776
}
37893777

3790-
@_versioned
37913778
internal func formIndex(after i: inout Index) {
3792-
i = index(after: i)
3779+
// FIXME: swift-3-indexing-model: optimize if possible.
3780+
i = i.successor()
37933781
}
37943782

37953783
@_versioned
@@ -3802,26 +3790,31 @@ internal final class _Cocoa${Self}Buffer : _HashBuffer {
38023790
return nil
38033791
}
38043792

3793+
%if Self == 'Set':
3794+
let allKeys = _stdlib_NSSet_allObjects(cocoaSet)
3795+
%elif Self == 'Dictionary':
3796+
let allKeys = _stdlib_NSDictionary_allKeys(cocoaDictionary)
3797+
%end
38053798
var keyIndex = -1
3806-
for i in 0..<allKeys._value.value {
3807-
if _stdlib_NSObject_isEqual(key, allKeys._value[i]) {
3799+
for i in 0..<allKeys.value {
3800+
if _stdlib_NSObject_isEqual(key, allKeys[i]) {
38083801
keyIndex = i
38093802
break
38103803
}
38113804
}
38123805
_sanityCheck(keyIndex >= 0,
38133806
"key was found in fast path, but not found later?")
3814-
return Index(value: keyIndex)
3807+
return Index(cocoa${Self}, allKeys, keyIndex)
38153808
}
38163809

38173810
internal func assertingGet(_ i: Index) -> SequenceElement {
38183811
%if Self == 'Set':
3819-
let value: Value? = allKeys._value[i.currentKeyIndex]
3812+
let value: Value? = i.allKeys[i.currentKeyIndex]
38203813
_sanityCheck(value != nil, "item not found in underlying NS${Self}")
38213814
return value!
38223815
%elif Self == 'Dictionary':
3823-
let key: Key = allKeys._value[i.currentKeyIndex]
3824-
let value: Value = cocoaDictionary.objectFor(key)!
3816+
let key: Key = i.allKeys[i.currentKeyIndex]
3817+
let value: Value = i.cocoaDictionary.objectFor(key)!
38253818
return (key, value)
38263819
%end
38273820

@@ -3850,33 +3843,29 @@ internal final class _Cocoa${Self}Buffer : _HashBuffer {
38503843

38513844
}
38523845

3853-
internal init(cocoa${Self}: _NS${Self}) {
3854-
self.cocoa${Self} = cocoa${Self}
3855-
}
3856-
38573846
@discardableResult
3858-
internal func updateValue(_ value: Value, forKey key: Key) -> Value? {
3847+
internal mutating func updateValue(_ value: Value, forKey key: Key) -> Value? {
38593848
_sanityCheckFailure("cannot mutate NS${Self}")
38603849
}
38613850

38623851
@discardableResult
3863-
internal func insert(
3852+
internal mutating func insert(
38643853
_ value: Value, forKey key: Key
38653854
) -> (inserted: Bool, memberAfterInsert: Value) {
38663855
_sanityCheckFailure("cannot mutate NS${Self}")
38673856
}
38683857

38693858
@discardableResult
3870-
internal func remove(at index: Index) -> SequenceElement {
3859+
internal mutating func remove(at index: Index) -> SequenceElement {
38713860
_sanityCheckFailure("cannot mutate NS${Self}")
38723861
}
38733862

38743863
@discardableResult
3875-
internal func removeValue(forKey key: Key) -> Value? {
3864+
internal mutating func removeValue(forKey key: Key) -> Value? {
38763865
_sanityCheckFailure("cannot mutate NS${Self}")
38773866
}
38783867

3879-
internal func removeAll(keepingCapacity keepCapacity: Bool) {
3868+
internal mutating func removeAll(keepingCapacity keepCapacity: Bool) {
38803869
_sanityCheckFailure("cannot mutate NS${Self}")
38813870
}
38823871

@@ -4465,9 +4454,8 @@ internal enum _Variant${Self}Buffer<${TypeParametersDecl}> : _HashBuffer {
44654454
//
44664455
// FIXME(performance): fuse data migration and element deletion into one
44674456
// operation.
4468-
let cocoaIndex = index._cocoaIndex
4469-
let anyObjectKey: AnyObject =
4470-
cocoaBuffer.allKeys._value[cocoaIndex.currentKeyIndex]
4457+
let index = index._cocoaIndex
4458+
let anyObjectKey: AnyObject = index.allKeys[index.currentKeyIndex]
44714459
migrateDataToNativeBuffer(cocoaBuffer)
44724460
let key = _forceBridgeFromObjectiveC(anyObjectKey, Key.self)
44734461
let value = nativeRemoveObject(forKey: key)
@@ -4628,11 +4616,61 @@ extension _Native${Self}Index {
46284616
#if _runtime(_ObjC)
46294617
@_versioned
46304618
internal struct _Cocoa${Self}Index : Comparable {
4631-
/// Index into `allKeys` on the CocoaSelfBuffer
4619+
// Assumption: we rely on NSDictionary.getObjects when being
4620+
// repeatedly called on the same NSDictionary, returning items in the same
4621+
// order every time.
4622+
// Similarly, the same assumption holds for NSSet.allObjects.
4623+
4624+
/// A reference to the NS${Self}, which owns members in `allObjects`,
4625+
/// or `allKeys`, for NSSet and NSDictionary respectively.
4626+
internal let cocoa${Self}: _NS${Self}
4627+
// FIXME: swift-3-indexing-model: try to remove the cocoa reference, but make
4628+
// sure that we have a safety check for accessing `allKeys`. Maybe move both
4629+
// into the dictionary/set itself.
4630+
4631+
/// An unowned array of keys.
4632+
internal var allKeys: _HeapBuffer<Int, AnyObject>
4633+
4634+
/// Index into `allKeys`
46324635
internal var currentKeyIndex: Int
46334636

4634-
internal init(value: Int) {
4635-
currentKeyIndex = value
4637+
internal init(_ cocoa${Self}: _NS${Self}, startIndex: ()) {
4638+
self.cocoa${Self} = cocoa${Self}
4639+
%if Self == 'Set':
4640+
self.allKeys = _stdlib_NSSet_allObjects(cocoaSet)
4641+
%elif Self == 'Dictionary':
4642+
self.allKeys = _stdlib_NSDictionary_allKeys(cocoaDictionary)
4643+
%end
4644+
self.currentKeyIndex = 0
4645+
}
4646+
4647+
internal init(_ cocoa${Self}: _NS${Self}, endIndex: ()) {
4648+
self.cocoa${Self} = cocoa${Self}
4649+
%if Self == 'Set':
4650+
self.allKeys = _stdlib_NS${Self}_allObjects(cocoa${Self})
4651+
%elif Self == 'Dictionary':
4652+
self.allKeys = _stdlib_NS${Self}_allKeys(cocoa${Self})
4653+
%end
4654+
self.currentKeyIndex = allKeys.value
4655+
}
4656+
4657+
internal init(_ cocoa${Self}: _NS${Self},
4658+
_ allKeys: _HeapBuffer<Int, AnyObject>,
4659+
_ currentKeyIndex: Int
4660+
) {
4661+
self.cocoa${Self} = cocoa${Self}
4662+
self.allKeys = allKeys
4663+
self.currentKeyIndex = currentKeyIndex
4664+
}
4665+
4666+
/// Returns the next consecutive value after `self`.
4667+
///
4668+
/// - Precondition: The next value is representable.
4669+
internal func successor() -> _Cocoa${Self}Index {
4670+
// FIXME: swift-3-indexing-model: remove this method.
4671+
_precondition(
4672+
currentKeyIndex < allKeys.value, "cannot increment endIndex")
4673+
return _Cocoa${Self}Index(cocoa${Self}, allKeys, currentKeyIndex + 1)
46364674
}
46374675
}
46384676

0 commit comments

Comments
 (0)