@@ -396,13 +396,13 @@ public struct Dictionary<Key: Hashable, Value> {
396396
397397 @inlinable
398398 internal init ( _native: __owned _NativeDictionary< Key , Value > ) {
399- _variant = . native ( _native)
399+ _variant = _Variant ( native : _native)
400400 }
401401
402402#if _runtime(_ObjC)
403403 @inlinable
404404 internal init ( _cocoa: __owned _CocoaDictionary) {
405- _variant = . cocoa ( _cocoa)
405+ _variant = _Variant ( cocoa : _cocoa)
406406 }
407407
408408 /// Private initializer used for bridging.
@@ -444,7 +444,7 @@ public struct Dictionary<Key: Hashable, Value> {
444444 /// reallocating its storage buffer.
445445 public // FIXME(reserveCapacity): Should be inlinable
446446 init ( minimumCapacity: Int ) {
447- _variant = . native ( _NativeDictionary ( capacity: minimumCapacity) )
447+ _variant = _Variant ( native : _NativeDictionary ( capacity: minimumCapacity) )
448448 }
449449
450450 /// Creates a new dictionary from the key-value pairs in the given sequence.
@@ -1316,8 +1316,12 @@ extension Dictionary {
13161316 return Values ( _dictionary: self )
13171317 }
13181318 _modify {
1319- var values = Values ( _dictionary: self )
1320- _variant = . native( _NativeDictionary ( ) )
1319+ var values : Values
1320+ do {
1321+ var temp = _Variant ( dummy: ( ) )
1322+ swap ( & temp, & _variant)
1323+ values = Values ( _variant: temp)
1324+ }
13211325 yield & values
13221326 self . _variant = values. _variant
13231327 }
@@ -1404,10 +1408,26 @@ extension Dictionary {
14041408 @inlinable
14051409 public static func == ( lhs: Keys , rhs: Keys ) -> Bool {
14061410 // Equal if the two dictionaries share storage.
1407- if case ( . native( let ln) , . native( let rn) ) = ( lhs. _variant, rhs. _variant) ,
1408- ln. _storage === rn. _storage {
1411+ #if _runtime(_ObjC)
1412+ if
1413+ lhs. _variant. isNative,
1414+ rhs. _variant. isNative,
1415+ lhs. _variant. asNative. _storage === rhs. _variant. asNative. _storage
1416+ {
1417+ return true
1418+ }
1419+ if
1420+ !lhs. _variant. isNative,
1421+ !rhs. _variant. isNative,
1422+ lhs. _variant. asCocoa. object === rhs. _variant. asCocoa. object
1423+ {
1424+ return true
1425+ }
1426+ #else
1427+ if lhs. _variant. asNative. _storage === rhs. _variant. asNative. _storage {
14091428 return true
14101429 }
1430+ #endif
14111431
14121432 // Not equal if the dictionaries are different sizes.
14131433 if lhs. count != rhs. count {
@@ -1517,21 +1537,15 @@ extension Dictionary {
15171537 @inlinable
15181538 public mutating func swapAt( _ i: Index , _ j: Index ) {
15191539 guard i != j else { return }
1520- let ( a, b) : ( _HashTable . Bucket , _HashTable . Bucket )
1521- switch _variant {
1522- case . native( let native) :
1523- a = native. validatedBucket ( for: i)
1524- b = native. validatedBucket ( for: j)
15251540#if _runtime(_ObjC)
1526- case . cocoa( let cocoa) :
1527- _variant. cocoaPath ( )
1528- let native = _NativeDictionary < Key , Value > ( cocoa)
1529- a = native. validatedBucket ( for: i)
1530- b = native. validatedBucket ( for: j)
1531- _variant = . native( native)
1532- #endif
1541+ if !_variant. isNative {
1542+ _variant = . init( native: _NativeDictionary ( _variant. asCocoa) )
15331543 }
1544+ #endif
15341545 let isUnique = _variant. isUniquelyReferenced ( )
1546+ let native = _variant. asNative
1547+ let a = native. validatedBucket ( for: i)
1548+ let b = native. validatedBucket ( for: j)
15351549 _variant. asNative. swapValuesAt ( a, b, isUnique: isUnique)
15361550 }
15371551 }
@@ -1606,51 +1620,20 @@ extension Dictionary.Values {
16061620extension Dictionary : Equatable where Value: Equatable {
16071621 @inlinable
16081622 public static func == ( lhs: [ Key : Value ] , rhs: [ Key : Value ] ) -> Bool {
1609- switch ( lhs. _variant, rhs. _variant) {
1610- case ( . native( let lhsNative) , . native( let rhsNative) ) :
1611-
1612- if lhsNative. _storage === rhsNative. _storage {
1613- return true
1614- }
1615-
1616- if lhsNative. count != rhsNative. count {
1617- return false
1618- }
1619-
1620- for (k, v) in lhs {
1621- let ( bucket, found) = rhsNative. find ( k)
1622- guard found, rhsNative. uncheckedValue ( at: bucket) == v else {
1623- return false
1624- }
1625- }
1626- return true
1627-
1628- #if _runtime(_ObjC)
1629- case ( . cocoa( let lhsCocoa) , . cocoa( let rhsCocoa) ) :
1630- return lhsCocoa == rhsCocoa
1631-
1632- case ( . native( let lhsNative) , . cocoa( let rhsCocoa) ) :
1633- if lhsNative. count != rhsCocoa. count {
1634- return false
1635- }
1636-
1637- defer { _fixLifetime ( lhsNative) }
1638- for bucket in lhsNative. hashTable {
1639- let key = lhsNative. uncheckedKey ( at: bucket)
1640- let value = lhsNative. uncheckedValue ( at: bucket)
1641- guard
1642- let rhsValue = rhsCocoa. lookup ( _bridgeAnythingToObjectiveC ( key) ) ,
1643- value == _forceBridgeFromObjectiveC ( rhsValue, Value . self)
1644- else {
1645- return false
1646- }
1647- }
1648- return true
1649-
1650- case ( . cocoa, . native) :
1651- return rhs == lhs
1652- #endif
1653- }
1623+ #if _runtime(_ObjC)
1624+ switch ( lhs. _variant. isNative, rhs. _variant. isNative) {
1625+ case ( true , true ) :
1626+ return lhs. _variant. asNative. isEqual ( to: rhs. _variant. asNative)
1627+ case ( false , false ) :
1628+ return lhs. _variant. asCocoa. isEqual ( to: rhs. _variant. asCocoa)
1629+ case ( true , false ) :
1630+ return lhs. _variant. asNative. isEqual ( to: rhs. _variant. asCocoa)
1631+ case ( false , true ) :
1632+ return rhs. _variant. asNative. isEqual ( to: lhs. _variant. asCocoa)
1633+ }
1634+ #else
1635+ return lhs. _variant. asNative. isEqual ( to: rhs. _variant. asNative)
1636+ #endif
16541637 }
16551638}
16561639
@@ -1860,20 +1843,18 @@ extension Dictionary.Index {
18601843 var handle = _asCocoa. handleBitPattern
18611844 return handle == 0 || _isUnique_native ( & handle)
18621845 }
1863- #endif
18641846
18651847 @usableFromInline @_transparent
18661848 internal var _isNative : Bool {
18671849 switch _variant {
18681850 case . native:
18691851 return true
1870- #if _runtime(_ObjC)
18711852 case . cocoa:
18721853 _cocoaPath ( )
18731854 return false
1874- #endif
18751855 }
18761856 }
1857+ #endif
18771858
18781859 @usableFromInline @_transparent
18791860 internal var _asNative : _HashTable . Index {
@@ -1958,19 +1939,17 @@ extension Dictionary.Index: Comparable {
19581939extension Dictionary . Index : Hashable {
19591940 public // FIXME(cocoa-index): Make inlinable
19601941 func hash( into hasher: inout Hasher ) {
1961- #if _runtime(_ObjC)
1962- switch _variant {
1963- case . native( let nativeIndex) :
1964- hasher. combine ( 0 as UInt8 )
1965- hasher. combine ( nativeIndex. bucket. offset)
1966- case . cocoa( let cocoaIndex) :
1967- _cocoaPath ( )
1942+ #if _runtime(_ObjC)
1943+ guard _isNative else {
19681944 hasher. combine ( 1 as UInt8 )
1969- hasher. combine ( cocoaIndex. storage. currentKeyIndex)
1945+ hasher. combine ( _asCocoa. storage. currentKeyIndex)
1946+ return
19701947 }
1971- #else
1948+ hasher . combine ( 0 as UInt8 )
19721949 hasher. combine ( _asNative. bucket. offset)
1973- #endif
1950+ #else
1951+ hasher. combine ( _asNative. bucket. offset)
1952+ #endif
19741953 }
19751954}
19761955
@@ -2034,6 +2013,17 @@ extension Dictionary.Iterator {
20342013 _conditionallyUnreachable ( )
20352014 }
20362015 }
2016+
2017+ @usableFromInline @_transparent
2018+ internal var _isNative : Bool {
2019+ switch _variant {
2020+ case . native:
2021+ return true
2022+ case . cocoa:
2023+ _cocoaPath ( )
2024+ return false
2025+ }
2026+ }
20372027#endif
20382028
20392029 @usableFromInline @_transparent
@@ -2052,6 +2042,21 @@ extension Dictionary.Iterator {
20522042 self . _variant = . native( newValue)
20532043 }
20542044 }
2045+
2046+ #if _runtime(_ObjC)
2047+ @usableFromInline @_transparent
2048+ internal var _asCocoa : _CocoaDictionary . Iterator {
2049+ get {
2050+ switch _variant {
2051+ case . native:
2052+ _sanityCheckFailure ( " internal error: does not contain a Cocoa index " )
2053+ case . cocoa( let cocoa) :
2054+ return cocoa
2055+ }
2056+ }
2057+ }
2058+ #endif
2059+
20552060}
20562061
20572062extension Dictionary . Iterator : IteratorProtocol {
@@ -2062,20 +2067,17 @@ extension Dictionary.Iterator: IteratorProtocol {
20622067 @inlinable
20632068 @inline ( __always)
20642069 public mutating func next( ) -> ( key: Key , value: Value ) ? {
2065- switch _variant {
2066- case . native:
2067- return _asNative. next ( )
20682070#if _runtime(_ObjC)
2069- case . cocoa( let cocoaIterator) :
2070- _cocoaPath ( )
2071- if let ( cocoaKey, cocoaValue) = cocoaIterator. next ( ) {
2071+ guard _isNative else {
2072+ if let ( cocoaKey, cocoaValue) = _asCocoa. next ( ) {
20722073 let nativeKey = _forceBridgeFromObjectiveC ( cocoaKey, Key . self)
20732074 let nativeValue = _forceBridgeFromObjectiveC ( cocoaValue, Value . self)
20742075 return ( nativeKey, nativeValue)
20752076 }
20762077 return nil
2077- #endif
20782078 }
2079+ #endif
2080+ return _asNative. next ( )
20792081 }
20802082}
20812083
0 commit comments