While experimenting with AnyHashable, I was surprised that the following code actually works.
import Foundation
struct S: Hashable {
var a: Int
}
let hashable = AnyHashable(S(a: 5))
let object: NSObject = hashable as NSObject
print(object.isEqual(S(a: 5))) // prints true
How is it that AnyHashable which is a struct can always be cast to an NSObject even when wrapping a value type?
i'm not certain about the details, but the SIL shows that the cast is calling the function _bridgeAnythingToObjectiveC, which, if it works as named, i would expect to produce this effect .
surprisingly the cast still compiles if you remove the Foundation import and swap NSObject for AnyObject, and even if you pass the -disable-objc-interop frontend flag (godbolt):
struct S: Hashable {}
func test(_ a: AnyHashable) {
let obj = a as AnyObject // ✅
_ = obj
}
test(AnyHashable(S()))
there is this code here in the implementation of AnyHashable which might be related, but also seems like it maybe shouldn't work for non-Darwin targets (yet still does)?
S() as AnyObject // Compiles
S() as AnyHashable // Compiles
import typealias Foundation.NSObject
S() as NSObject // Cannot convert value of type 'S' to type 'NSObject' in coercion
S() as AnyHashable as NSObject // Compiles