@@ -396,13 +396,13 @@ public struct Dictionary<Key: Hashable, Value> {
396
396
397
397
@inlinable
398
398
internal init ( _native: __owned _NativeDictionary< Key , Value > ) {
399
- _variant = . native ( _native)
399
+ _variant = _Variant ( native : _native)
400
400
}
401
401
402
402
#if _runtime(_ObjC)
403
403
@inlinable
404
404
internal init ( _cocoa: __owned _CocoaDictionary) {
405
- _variant = . cocoa ( _cocoa)
405
+ _variant = _Variant ( cocoa : _cocoa)
406
406
}
407
407
408
408
/// Private initializer used for bridging.
@@ -444,7 +444,7 @@ public struct Dictionary<Key: Hashable, Value> {
444
444
/// reallocating its storage buffer.
445
445
public // FIXME(reserveCapacity): Should be inlinable
446
446
init ( minimumCapacity: Int ) {
447
- _variant = . native ( _NativeDictionary ( capacity: minimumCapacity) )
447
+ _variant = _Variant ( native : _NativeDictionary ( capacity: minimumCapacity) )
448
448
}
449
449
450
450
/// Creates a new dictionary from the key-value pairs in the given sequence.
@@ -1316,8 +1316,12 @@ extension Dictionary {
1316
1316
return Values ( _dictionary: self )
1317
1317
}
1318
1318
_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
+ }
1321
1325
yield & values
1322
1326
self . _variant = values. _variant
1323
1327
}
@@ -1404,10 +1408,26 @@ extension Dictionary {
1404
1408
@inlinable
1405
1409
public static func == ( lhs: Keys , rhs: Keys ) -> Bool {
1406
1410
// 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 {
1409
1428
return true
1410
1429
}
1430
+ #endif
1411
1431
1412
1432
// Not equal if the dictionaries are different sizes.
1413
1433
if lhs. count != rhs. count {
@@ -1517,21 +1537,15 @@ extension Dictionary {
1517
1537
@inlinable
1518
1538
public mutating func swapAt( _ i: Index , _ j: Index ) {
1519
1539
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)
1525
1540
#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) )
1533
1543
}
1544
+ #endif
1534
1545
let isUnique = _variant. isUniquelyReferenced ( )
1546
+ let native = _variant. asNative
1547
+ let a = native. validatedBucket ( for: i)
1548
+ let b = native. validatedBucket ( for: j)
1535
1549
_variant. asNative. swapValuesAt ( a, b, isUnique: isUnique)
1536
1550
}
1537
1551
}
@@ -1606,51 +1620,20 @@ extension Dictionary.Values {
1606
1620
extension Dictionary : Equatable where Value: Equatable {
1607
1621
@inlinable
1608
1622
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
1654
1637
}
1655
1638
}
1656
1639
@@ -1860,20 +1843,18 @@ extension Dictionary.Index {
1860
1843
var handle = _asCocoa. handleBitPattern
1861
1844
return handle == 0 || _isUnique_native ( & handle)
1862
1845
}
1863
- #endif
1864
1846
1865
1847
@usableFromInline @_transparent
1866
1848
internal var _isNative : Bool {
1867
1849
switch _variant {
1868
1850
case . native:
1869
1851
return true
1870
- #if _runtime(_ObjC)
1871
1852
case . cocoa:
1872
1853
_cocoaPath ( )
1873
1854
return false
1874
- #endif
1875
1855
}
1876
1856
}
1857
+ #endif
1877
1858
1878
1859
@usableFromInline @_transparent
1879
1860
internal var _asNative : _HashTable . Index {
@@ -1958,19 +1939,17 @@ extension Dictionary.Index: Comparable {
1958
1939
extension Dictionary . Index : Hashable {
1959
1940
public // FIXME(cocoa-index): Make inlinable
1960
1941
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 {
1968
1944
hasher. combine ( 1 as UInt8 )
1969
- hasher. combine ( cocoaIndex. storage. currentKeyIndex)
1945
+ hasher. combine ( _asCocoa. storage. currentKeyIndex)
1946
+ return
1970
1947
}
1971
- #else
1948
+ hasher . combine ( 0 as UInt8 )
1972
1949
hasher. combine ( _asNative. bucket. offset)
1973
- #endif
1950
+ #else
1951
+ hasher. combine ( _asNative. bucket. offset)
1952
+ #endif
1974
1953
}
1975
1954
}
1976
1955
@@ -2034,6 +2013,17 @@ extension Dictionary.Iterator {
2034
2013
_conditionallyUnreachable ( )
2035
2014
}
2036
2015
}
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
+ }
2037
2027
#endif
2038
2028
2039
2029
@usableFromInline @_transparent
@@ -2052,6 +2042,21 @@ extension Dictionary.Iterator {
2052
2042
self . _variant = . native( newValue)
2053
2043
}
2054
2044
}
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
+
2055
2060
}
2056
2061
2057
2062
extension Dictionary . Iterator : IteratorProtocol {
@@ -2062,20 +2067,17 @@ extension Dictionary.Iterator: IteratorProtocol {
2062
2067
@inlinable
2063
2068
@inline ( __always)
2064
2069
public mutating func next( ) -> ( key: Key , value: Value ) ? {
2065
- switch _variant {
2066
- case . native:
2067
- return _asNative. next ( )
2068
2070
#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 ( ) {
2072
2073
let nativeKey = _forceBridgeFromObjectiveC ( cocoaKey, Key . self)
2073
2074
let nativeValue = _forceBridgeFromObjectiveC ( cocoaValue, Value . self)
2074
2075
return ( nativeKey, nativeValue)
2075
2076
}
2076
2077
return nil
2077
- #endif
2078
2078
}
2079
+ #endif
2080
+ return _asNative. next ( )
2079
2081
}
2080
2082
}
2081
2083
0 commit comments