Why isn’t AnyHashable implemented in pure Swift?

This is the intended behavior. See here and here for the implementation and explanations. (It is also alluded to here by @lorentey in explaining the implementation of Hashable enhancements. See also this earlier discussion which lays out the problem in more detail.)

We have had several Swift Evolution proposals to do with NSNumber behavior in Swift; this is not some temporary hack but part of the final design, and is now consistent across all platforms. A previous bridging behavior (SE-0139) was ultimately deemed suboptimal and abandoned with SE-0170; notably, this bridging design was adopted well after AnyHashable was added in SE-0131. In fact, in motivating SE-0170, the authors write:

No matter if you are using Objective-C in your app/framework in addition to Swift or not the behavior should be easily understood and consistent.


I'm not aware of any guarantee that AnyHashable preserves the hashValue of its wrapped instance. In fact, it seems that the point of the _HasCustomAnyHashableRepresentation protocol is to permit otherwise.

The example given in the documentation for AnyHashable (written for SE-0131) is now outdated; it was actually corrected for the next version of Swift in PR #21550. In that conversation, @Joe_Groff explains:

AnyHashable should behave this way for any types that are transitively as? -castable, so you can get a String out as an NSString and v.v., an Array<T> as an NSArray , and so on. The standard library integer and floating-point types as well as CGFloat and Decimal all bridge to NSNumber , and NSNumber bridges back to any of those types if the value is exactly representable.