-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Foundation] Modernize hashing in Foundation's Swift-only types #23832
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
668c1f0
68e6449
46225d7
569e380
73ad830
81567ed
0867f7e
8b7adb3
741122a
73be6b8
c1049e7
a000422
9c46858
2d5520e
5e451e6
4bdc458
afa2539
b41eb97
10cb05a
590f407
23cc719
a23c3f3
28e4688
6f40a4a
b711ed9
f859dd1
2ab2431
7f1dd3e
582b65b
13bc567
6647c50
530687f
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 |
---|---|---|
|
@@ -142,14 +142,10 @@ public struct Date : ReferenceConvertible, Comparable, Equatable { | |
*/ | ||
public static let distantPast = Date(timeIntervalSinceReferenceDate: -63114076800.0) | ||
|
||
public var hashValue: Int { | ||
if #available(macOS 10.12, iOS 10.0, *) { | ||
return Int(bitPattern: __CFHashDouble(_time)) | ||
} else { // 10.11 and previous behavior fallback; this must allocate a date to reference the hash value and then throw away the reference | ||
return NSDate(timeIntervalSinceReferenceDate: _time).hash | ||
} | ||
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. Note: There is no need to emulate NSDate's hashing behavior, or the behavior of any previous version of Granted, in this case (like with many other hashValues removed by this PR), 5.0 did not vend properly seeded hashes, so in theory someone could be relying on the exact values returned. I believe this is still a low-risk change; and since this is not inlinable code, we have the option to re-add specific |
||
public func hash(into hasher: inout Hasher) { | ||
hasher.combine(_time) | ||
} | ||
|
||
/// Compare two `Date` values. | ||
public func compare(_ other: Date) -> ComparisonResult { | ||
if _time < other.timeIntervalSinceReferenceDate { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -155,15 +155,11 @@ public struct DateInterval : ReferenceConvertible, Comparable, Hashable, Codable | |
return false | ||
} | ||
|
||
public var hashValue: Int { | ||
var buf: (UInt, UInt) = (UInt(start.timeIntervalSinceReferenceDate), UInt(end.timeIntervalSinceReferenceDate)) | ||
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. Using the
The new code is careful to match the implementation of |
||
return withUnsafeMutablePointer(to: &buf) { | ||
$0.withMemoryRebound(to: UInt8.self, capacity: 2 * MemoryLayout<UInt>.size / MemoryLayout<UInt8>.size) { | ||
return Int(bitPattern: CFHashBytes($0, CFIndex(MemoryLayout<UInt>.size * 2))) | ||
} | ||
} | ||
public func hash(into hasher: inout Hasher) { | ||
hasher.combine(start) | ||
hasher.combine(duration) | ||
} | ||
|
||
@available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) | ||
public static func ==(lhs: DateInterval, rhs: DateInterval) -> Bool { | ||
return lhs.start == rhs.start && lhs.duration == rhs.duration | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,8 +36,19 @@ public struct Measurement<UnitType : Unit> : ReferenceConvertible, Comparable, E | |
self.unit = unit | ||
} | ||
|
||
public var hashValue: Int { | ||
return Int(bitPattern: __CFHashDouble(value)) | ||
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 of (A version of this change was originally submitted as #20879.) |
||
public func hash(into hasher: inout Hasher) { | ||
// Warning: The canonicalization performed here needs to be kept in | ||
// perfect sync with the definition of == below. The floating point | ||
// values that are compared there must match exactly with the values fed | ||
// to the hasher here, or hashing would break. | ||
if let dimension = unit as? Dimension { | ||
// We don't need to feed the base unit to the hasher here; all | ||
// dimensional measurements of the same type share the same unit. | ||
hasher.combine(dimension.converter.baseUnitValue(fromValue: value)) | ||
} else { | ||
hasher.combine(unit) | ||
hasher.combine(value) | ||
} | ||
} | ||
} | ||
|
||
|
@@ -170,6 +181,10 @@ extension Measurement { | |
/// If `lhs.unit == rhs.unit`, returns `lhs.value == rhs.value`. Otherwise, converts `rhs` to the same unit as `lhs` and then compares the resulting values. | ||
/// - returns: `true` if the measurements are equal. | ||
public static func ==<LeftHandSideType, RightHandSideType>(lhs: Measurement<LeftHandSideType>, rhs: Measurement<RightHandSideType>) -> Bool { | ||
// Warning: This defines an equivalence relation that needs to be kept | ||
// in perfect sync with the hash(into:) definition above. The floating | ||
// point values that are fed to the hasher there must match exactly with | ||
// the values compared here, or hashing would break. | ||
if lhs.unit == rhs.unit { | ||
return lhs.value == rhs.value | ||
} else { | ||
|
Uh oh!
There was an error while loading. Please reload this page.