NSObject is Hashable but a protocol that adopts NSObject is not?

NSObjectProtocol doesn't inherit from Hashable. That's the crucial problem here.

It can't actually inherit from Hashable because Hashable requires a method called hashValue while NSObjectProtocol requires a method called hash.

On the other hand, NSObject class can implement both NSObjectProtocol and Hashable.

The same problem happens with Equatable.

Edit:

There is another more subtle problem. You cannot use a protocol somewhere where Equatable is expected, you always need to use a class type or a value type that adopts Equatable. The reason is that it's not enough for a key to adopt Equatable, all the keys in the dictionary have to be equatable with each other.

For example, if you have a class A and a class B, both conforming to Equatable, then you can compare instances of A with other instances of A and you can compare instances of B with other instances of B but you cannot compare instances of A with instances of B. That's why you cannot use instances of A and instances of B as keys in the same dictionary.

Note that every NSObject is equatable with any other NSObject, so NSObject is an allowed type for keys in a dictionary.