I forgot to mention that BTrees implement Ord. You can nest them in any number of levels, as long as all keys and values other than the values of the topmost BTreeMap implement Ord.
To have HashMaps implement Hash, we need to iterate through their contained hashes in a consistent order. We only need to access hashes to compute a hash. (All hashes are approximate, anyway.) Most of the time, logically equal maps have the same element ordering. There are two obstacles to making sure our iteration order is consistent regardless of element ordering.
First, whenever a map contains groups of similar hashes, the element ordering depends on the original order of insertion. Fortunately, in other cases, a consistent order is guaranteed by Robin Hood hashing. To consistently iterate through all hashes, we need to detect groups of similar hashes and grab them in an order that depends only on their exact values. By “similar” hashes, I mean hashes that are congruent modulo capacity – in other words, some of their least significant bits are equal.
Second, logically equal maps can have different capacities. For maps with “inflated” capacities, we need to divide tables into parts that are equal in size to the smallest map’s table. To iterate through a map in the right order, we must zip all its parts to get an iterator that visits positions that correspond to a single position in the smallest map. Collisions still must be dealt with somehow. Even with such complex iteration, there’s an issue with elements that were displaced across parts. In the smallest possible map, they are displaced to the beginning of the table, just like in a circular buffer.
As you can see, this is a difficult but certainly solvable problem. In case you need help understanding Robin Hood hashing, here’s a visualization: http://pczarn.github.io/code/visualize/
edit: I tried to make the description better.