-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Modernize hashing in Foundation's Swift-only types #2118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
22a7465
eace6a6
d89f8f6
cabf8d5
9e37694
a876f49
b21face
456e7af
79631e0
d22bd38
fc63178
0ab9053
c81e113
86a038f
fa71c3d
dd402b9
2a60e2f
a921d69
ca19ca8
4175bef
18e010f
d69debd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -862,8 +862,9 @@ public struct Calendar : Hashable, Equatable, ReferenceConvertible, _MutableBoxi | |
public func hash(into hasher: inout Hasher) { | ||
// We implement hash ourselves, because we need to make sure autoupdating calendars have the same hash | ||
if _autoupdating { | ||
hasher.combine(1 as Int8) | ||
hasher.combine(false) | ||
} else { | ||
hasher.combine(true) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The original implementation here was ever so slightly wrong -- it had a variable-length hash encoding without discriminators to mark its boundaries, which could (theoretically) lead to collisions when multiple Granted, I doubt this would be a problem in practice; however, this change makes |
||
hasher.combine(_handle.map { $0 }) | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -828,11 +828,11 @@ public struct FileAttributeKey : RawRepresentable, Equatable, Hashable { | |
public init(rawValue: String) { | ||
self.rawValue = rawValue | ||
} | ||
public var hashValue: Int { | ||
return self.rawValue.hashValue | ||
|
||
public func hash(into hasher: inout Hasher) { | ||
hasher.combine(rawValue) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, esp. given that on Darwin it's the compiler that synthesizes those conformances, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I looked into it in more detail: on Darwin the hash implementations come from extensions on So if we removed these, then the same definitions would be found on |
||
} | ||
|
||
public static func ==(_ lhs: FileAttributeKey, _ rhs: FileAttributeKey) -> Bool { | ||
return lhs.rawValue == rhs.rawValue | ||
} | ||
|
@@ -873,8 +873,8 @@ public struct FileAttributeType : RawRepresentable, Equatable, Hashable { | |
self.rawValue = rawValue | ||
} | ||
|
||
public var hashValue: Int { | ||
return self.rawValue.hashValue | ||
public func hash(into hasher: inout Hasher) { | ||
hasher.combine(rawValue) | ||
} | ||
|
||
public static func ==(_ lhs: FileAttributeType, _ rhs: FileAttributeType) -> Bool { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,7 +46,7 @@ open class NSCharacterSet : NSObject, NSCopying, NSMutableCopying, NSCoding { | |
} | ||
|
||
open override var hash: Int { | ||
return Int(bitPattern: CFHash(_cfObject)) | ||
return Int(bitPattern: _CFNonObjCHash(_cfObject)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This fixes an infinite recursion in |
||
} | ||
|
||
open override func isEqual(_ value: Any?) -> Bool { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In protocol extensions that forward hashing to some core value, it is generally a good idea to implement both
hash(into:)
andhashValue
, so that hashing always matches the behavior of the underlying value. (But if we have to choose one, I'd go with justhash(into:)
.