Skip to content

[docs] Update AnyHashable documentation #29498

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

Merged
merged 5 commits into from
Feb 12, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 37 additions & 20 deletions stdlib/public/core/AnyHashable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,22 +107,33 @@ internal struct _ConcreteHashableBox<Base: Hashable>: _AnyHashableBox {
/// A type-erased hashable value.
///
/// The `AnyHashable` type forwards equality comparisons and hashing operations
/// to an underlying hashable value, hiding its specific underlying type.
/// to an underlying hashable value, hiding the type of the wrapped value.
///
/// Where conversion using `as` or `as?` is possible between two types (such as
/// `Int` and `NSNumber`), `AnyHashable` uses a canonical representation of the
/// type-erased value so that instances wrapping the same value of either type
/// compare as equal. For example, `AnyHashable(42)` compares as equal to
/// `AnyHashable(42 as NSNumber)`.
///
/// You can store mixed-type keys in dictionaries and other collections that
/// require `Hashable` conformance by wrapping mixed-type keys in
/// `AnyHashable` instances:
///
/// let descriptions: [AnyHashable: Any] = [
/// AnyHashable("😄"): "emoji",
/// AnyHashable(42): "an Int",
/// AnyHashable(Int8(43)): "an Int8",
/// AnyHashable(Set(["a", "b"])): "a set of strings"
/// 42: "an Int",
/// 43 as Int8: "an Int8",
/// ["a", "b"] as Set: "a set of strings"
/// ]
/// print(descriptions[AnyHashable(42)]!) // prints "an Int"
/// print(descriptions[AnyHashable(45)]) // prints "nil"
/// print(descriptions[AnyHashable(Int8(43))]!) // prints "an Int8"
/// print(descriptions[AnyHashable(Set(["a", "b"]))]!) // prints "a set of strings"
/// print(descriptions[42]!) // prints "an Int"
/// print(descriptions[42 as Int8]!) // prints "an Int"
/// print(descriptions[43 as Int8]!) // prints "an Int8"
/// print(descriptions[44]) // prints "nil"
/// print(descriptions[["a", "b"] as Set]!) // prints "a set of strings"
///
/// Note that `AnyHashable` does not guarantee that it preserves the hash
/// encoding of wrapped values. Do not rely on `AnyHashable` generating such
/// compatible hashes, as the hash encoding that it uses may change between any
/// two releases of the standard library.
@frozen
public struct AnyHashable {
internal var _box: _AnyHashableBox
Expand Down Expand Up @@ -154,7 +165,7 @@ public struct AnyHashable {
/// The value wrapped by this instance.
///
/// The `base` property can be cast back to its original type using one of
/// the casting operators (`as?`, `as!`, or `as`).
/// the type casting operators (`as?`, `as!`, or `as`).
///
/// let anyMessage = AnyHashable("Hello world!")
/// if let unwrappedMessage = anyMessage.base as? String {
Expand Down Expand Up @@ -189,11 +200,23 @@ public struct AnyHashable {

extension AnyHashable: Equatable {
/// Returns a Boolean value indicating whether two type-erased hashable
/// instances wrap the same type and value.
/// instances wrap the same value.
///
/// Two instances of `AnyHashable` compare as equal if and only if the
/// underlying types have the same conformance to the `Equatable` protocol
/// and the underlying values compare as equal.
/// `AnyHashable` considers bridged counterparts (such as a `String` and an
/// `NSString`) of the same value to be equivalent when type-erased. If those
/// compatible types use different definitions for equality, values that were
/// originally distinct might compare as equal when they are converted to
/// `AnyHashable`:
///
/// let string1 = "café"
/// let string2 = "cafe\u{301}" // U+301 COMBINING ACUTE ACCENT
/// let nsString1 = string1 as NSString
/// let nsString2 = string2 as NSString
/// let typeErased1 = nsString1 as AnyHashable
/// let typeErased2 = nsString2 as AnyHashable
/// print(string1 == string2) // prints "true"
/// print(nsString1 == nsString2) // prints "false"
/// print(typeErased1 == typeErased2) // prints "true"
///
/// - Parameters:
/// - lhs: A type-erased hashable value.
Expand All @@ -204,16 +227,10 @@ extension AnyHashable: Equatable {
}

extension AnyHashable: Hashable {
/// The hash value.
public var hashValue: Int {
return _box._canonicalBox._hashValue
}

/// Hashes the essential components of this value by feeding them into the
/// given hasher.
///
/// - Parameter hasher: The hasher to use when combining the components
/// of this instance.
public func hash(into hasher: inout Hasher) {
_box._canonicalBox._hash(into: &hasher)
}
Expand Down