You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
AnyHashable violates the transitivity requirement of Equatable:
import Foundation
let a: AnyHashable = 42 as UInt8
let b: AnyHashable = NSNumber(value: 42)
let c: AnyHashable = 42
print(a == b, b == c, a == c) // => true, true, false
Hashable requires that if two values are equal, then they must hash the same way. AnyHashable violates this, too:
This makes AnyHashable unreliable for use in Sets or as Dictionary keys. Values inserted into a dictionary may or may not be retrievable, depending on the provenance of the lookup key. Set and Dictionary are sometimes able to detect these violations during rehashing operations; when that happens, they will (correctly!) trap with "Duplicate element found in Set"/"Duplicate key found in Dictionary".
With SE-0206 (Hashable Enhancements), we'd like to have integer types use distinct hash encodings; however, that would mean that even simple integer bridging cases would trigger the Hashable violation. (_HasCustomAnyHashableRepresentation's magical Equatable support implicitly assumes that every Swift type that bridges to the same Objective-C representation shares the same hash encoding.)
The text was updated successfully, but these errors were encountered:
I think the issue only affects bridging scenarios that involve NSNumber, but that includes Hashable collections of numbers like Array<Int>, Set<UInt32>, or Dictionary<String, Float>.
With SE-0170, integer/float bridging is not strictly type preserving any more; we need to update integers' and floating point numbers' AnyHashable representation to correctly take this into account.
leti = 42asUInt8letj = 42asInt64print(i == j) // => true (heterogeneous comparison, unrelated to Equatable)print(i.hashValue == j.hashValue) // true in 4.1, SE-0206 changes it to falseletai = iasAnyHashableletaj = jasAnyHashableprint(ai == aj) // false in 4.1, should be trueprint(ai.hashValue == aj.hashValue) // true in 4.1, should remain true with SE-0206
Environment
Tested in Swift 4.1 and above, including current master (as of 2018-04-22)
Additional Detail from JIRA
md5: dd7f6a2e9eb8a9ba1143f7ad79b73be4
Issue Description:
AnyHashable violates the transitivity requirement of Equatable:
Hashable requires that if two values are equal, then they must hash the same way. AnyHashable violates this, too:
This makes AnyHashable unreliable for use in Sets or as Dictionary keys. Values inserted into a dictionary may or may not be retrievable, depending on the provenance of the lookup key. Set and Dictionary are sometimes able to detect these violations during rehashing operations; when that happens, they will (correctly!) trap with "Duplicate element found in Set"/"Duplicate key found in Dictionary".
With SE-0206 (Hashable Enhancements), we'd like to have integer types use distinct hash encodings; however, that would mean that even simple integer bridging cases would trigger the Hashable violation. (_HasCustomAnyHashableRepresentation's magical Equatable support implicitly assumes that every Swift type that bridges to the same Objective-C representation shares the same hash encoding.)
The text was updated successfully, but these errors were encountered: