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 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
//===----------------------------------------------------------------------===//
//
// 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 can be hashed into a `Hasher` to produce 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 are
/// hashable by default. Some other types, such as optionals, arrays and ranges
/// automatically become hashable when their type arguments implement the same.
///
/// 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 implementing the `hash(into:)` method. For structs whose stored
/// properties are all `Hashable`, and for enum types that have all-`Hashable`
/// associated values, the compiler is able to provide an implementation of
/// `hash(into:)` automatically.
///
/// Hashing a value means feeding its essential components into a hash function,
/// represented by the `Hasher` type. Essential components are those that
/// contribute to the type's implementation of `Equatable`. Two instances that
/// are equal must feed the same values to `Hasher` in `hash(into:)`, in the
/// same order.
///
/// 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.
///
/// The compiler automatically synthesizes your custom type's `Hashable` and
/// requirements 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 `hash(into:)` method in your
/// custom type.
///
/// In your `hash(into:)` implementation, call `combine(_:)` on the provided
/// `Hasher` instance with the essential components of your 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
/// in a set. To add `Hashable` conformance, provide an `==` operator function
/// and implement the `hash(into:)` method.
///
/// extension GridPoint: Hashable {
/// static func == (lhs: GridPoint, rhs: GridPoint) -> Bool {
/// return lhs.x == rhs.x && lhs.y == rhs.y
/// }
///
/// func hash(into hasher: inout Hasher) {
/// hasher.combine(x)
/// hasher.combine(y)
/// }
/// }
///
/// The `hash(into:)` method in this example feeds the grid point's `x` and `y`
/// properties into the provided hasher. These properties are the same ones
/// used to test for equality in the `==` operator function.
///
/// 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.
///
/// - Important: `hashValue` is deprecated as a `Hashable` requirement. To
/// conform to `Hashable`, implement the `hash(into:)` requirement instead.
/// The compiler provides an implementation for `hashValue` for you.
var hashValue: Int { get }
/// Hashes the essential components of this value by feeding them into the
/// given hasher.
///
/// Implement this method to conform to the `Hashable` protocol. The
/// components used for hashing must be the same as the components compared
/// in your type's `==` operator implementation. Call `hasher.combine(_:)`
/// with each of these components.
///
/// - Important: In your implementation of `hash(into:)`,
/// don't call `finalize()` on the `hasher` instance provided,
/// or replace it with a different instance.
/// Doing so may become a compile-time error in the future.
///
/// - Parameter hasher: The hasher to use when combining the components
/// of this instance.
func hash(into hasher: inout Hasher)
// Raw top-level hashing interface. Some standard library types (mostly
// primitives) specialize this to eliminate small resiliency overheads. (This
// only matters for tiny keys.)
func _rawHashValue(seed: Int) -> Int
}
extension Hashable {
@inlinable
@inline(__always)
public func _rawHashValue(seed: Int) -> Int {
var hasher = Hasher(_seed: seed)
hasher.combine(self)
return hasher._finalize()
}
}
// Called by synthesized `hashValue` implementations.
@inlinable
@inline(__always)
public func _hashValue<H: Hashable>(for value: H) -> Int {
return value._rawHashValue(seed: 0)
}
// 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
}
|