forked from swiftlang/swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHashable.swift
148 lines (142 loc) · 6.05 KB
/
Hashable.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
/// A type that provides an integer hash value.
///
/// You can use any type that conforms to the `Hashable` protocol in a set or
/// as a dictionary key. Many types in the standard library conform to
/// `Hashable`: Strings, integers, floating-point and Boolean values, and even
/// sets provide a hash value by default. Your own custom types can be
/// hashable as well. When you define an enumeration without associated
/// values, it gains `Hashable` conformance automatically, and you can add
/// `Hashable` conformance to your other custom types by adding a single
/// `hashValue` property.
///
/// A hash value, provided by a type's `hashValue` property, is an integer that
/// is the same for any two instances that compare equally. That is, for two
/// instances `a` and `b` of the same type, if `a == b`, then
/// `a.hashValue == b.hashValue`. The reverse is not true: Two instances with
/// equal hash values are not necessarily equal to each other.
///
/// - Important: Hash values are not guaranteed to be equal across different
/// executions of your program. Do not save hash values to use in a future
/// execution.
///
/// Conforming to the Hashable Protocol
/// ===================================
///
/// To use your own custom type in a set or as the key type of a dictionary,
/// add `Hashable` conformance to your type. The `Hashable` protocol inherits
/// from the `Equatable` protocol, so you must also satisfy that protocol's
/// requirements.
///
/// A custom type's `Hashable` and `Equatable` requirements are automatically
/// synthesized by the compiler when you declare `Hashable` conformance in the
/// type's original declaration and your type meets these criteria:
///
/// - For a `struct`, all its stored properties must conform to `Hashable`.
/// - For an `enum`, all its associated values must conform to `Hashable`. (An
/// `enum` without associated values has `Hashable` conformance even without
/// the declaration.)
///
/// To customize your type's `Hashable` conformance, to adopt `Hashable` in a
/// type that doesn't meet the criteria listed above, or to extend an existing
/// type to conform to `Hashable`, implement the `hashValue` property in your
/// custom type. To ensure that your type meets the semantic requirements of
/// the `Hashable` and `Equatable` protocols, it's a good idea to also
/// customize your type's `Equatable` conformance to match.
///
/// As an example, consider a `GridPoint` type that describes a location in a
/// grid of buttons. Here's the initial declaration of the `GridPoint` type:
///
/// /// A point in an x-y coordinate system.
/// struct GridPoint {
/// var x: Int
/// var y: Int
/// }
///
/// You'd like to create a set of the grid points where a user has already
/// tapped. Because the `GridPoint` type is not hashable yet, it can't be used
/// as the `Element` type for a set. To add `Hashable` conformance, provide an
/// `==` operator function and a `hashValue` property.
///
/// extension GridPoint: Hashable {
/// var hashValue: Int {
/// return x.hashValue ^ y.hashValue &* 16777619
/// }
///
/// static func == (lhs: GridPoint, rhs: GridPoint) -> Bool {
/// return lhs.x == rhs.x && lhs.y == rhs.y
/// }
/// }
///
/// The `hashValue` property in this example combines the hash value of a grid
/// point's `x` property with the hash value of its `y` property multiplied by
/// a prime constant.
///
/// - Note: The example above is a reasonably good hash function for a
/// simple type. If you're writing a hash function for a custom type, choose
/// a hashing algorithm that is appropriate for the kinds of data your type
/// comprises. Set and dictionary performance depends on hash values that
/// minimize collisions for their associated element and key types,
/// respectively.
///
/// Now that `GridPoint` conforms to the `Hashable` protocol, you can create a
/// set of previously tapped grid points.
///
/// var tappedPoints: Set = [GridPoint(x: 2, y: 3), GridPoint(x: 4, y: 1)]
/// let nextTap = GridPoint(x: 0, y: 1)
/// if tappedPoints.contains(nextTap) {
/// print("Already tapped at (\(nextTap.x), \(nextTap.y)).")
/// } else {
/// tappedPoints.insert(nextTap)
/// print("New tap detected at (\(nextTap.x), \(nextTap.y)).")
/// }
/// // Prints "New tap detected at (0, 1).")
public protocol Hashable : Equatable {
/// The hash value.
///
/// Hash values are not guaranteed to be equal across different executions of
/// your program. Do not save hash values to use during a future execution.
var hashValue: Int { get }
/// Feed bits to be hashed into the hash function represented by `hasher`.
func _hash(into hasher: inout _Hasher)
}
extension Hashable {
@inlinable
@inline(__always)
public func _hash(into hasher: inout _Hasher) {
hasher.combine(self.hashValue)
}
}
// Called by synthesized `hashValue` implementations.
@inlinable
@inline(__always)
public func _hashValue<H: Hashable>(for value: H) -> Int {
var hasher = _Hasher()
hasher.combine(value)
return hasher.finalize()
}
// Called by the SwiftValue implementation.
@_silgen_name("_swift_stdlib_Hashable_isEqual_indirect")
internal func Hashable_isEqual_indirect<T : Hashable>(
_ lhs: UnsafePointer<T>,
_ rhs: UnsafePointer<T>
) -> Bool {
return lhs.pointee == rhs.pointee
}
// Called by the SwiftValue implementation.
@_silgen_name("_swift_stdlib_Hashable_hashValue_indirect")
internal func Hashable_hashValue_indirect<T : Hashable>(
_ value: UnsafePointer<T>
) -> Int {
return value.pointee.hashValue
}