These issues are really really tricky. I know it’s far from ideal, but we haven’t found a better solution at this point which allows having ranges and arrays compare equal.
I’ll stress again that the problem only affects hashing of heterogeneous collections currently. We need BigFloat just because of that corner case, which needs to be supported in Base. You’re right that we could make this need even less frequent by using a simpler algorithm when we know we don’t need to hash ranges and arrays the same, e.g. when looking up a key in a Dict{Vector{Int}}. But in general it’s needed e.g. for Dict{Any}, so we cannot completely get rid of it either.
Returning a 0 hash as a fallback is clever, but for it to work we would need to return 0 for all values, or at least for all collections we are going to compare which could be equal (e.g. various kinds of arrays and ranges with different number types). If the key type is Any, we don’t know in advance these types, so we would have to use 0 for all collections, which could be very slow. We may as well fall back to O(N) hashing in that case.
In general the approach of falling back, for collections with an abstract element type, to something slow but which doesn’t require a wider type like BigFloat is interesting. It would require adding a parallel, faster hash method which would be used for collections with concrete types (or more precisely for collections which cannot contain both ranges and arrays). We could pass a key/element type as the first argument to hash, which would allow us to implement whatever efficient solution we want. The essential idea would be that we would compute efficiently hashes which are only valid for a certain set of key types, but which shouldn’t be reused in a different context.