If we don’t decide hashCode explicitly, I think we’ll back ourselves into a bad default decision. Should the hashing logic for r.hashCode() be specified in a portable manner? I say, “no”, since there’s no good portable solution. Objects.hash is portable, but other than that is a poor algorithm.
Right now we don’t *specify* that we combine hashes using the base-31 polynomial, but we *do* use that stupid old thing. This is plausibly conservative but it will get it into a worse spot than necessary. We can buy ourselves some time by putting weasel words into Record::hashCode (or its successor) and ObjectMethods::bootstrap. We can promise that the hashCode result depends (typically) on all components of the record, and on nothing else. We should also explicitly state that the method for combining the bits is subject to change, very much like we specify that the iteration order for Set.of and Map.of is subject to change, like this: http://hg.openjdk.java.net/jdk/jdk/file/e9c11ba790b2/src/java.base/share/classes/java/util/Set.java#l83 Finally, for luck, we should add a pinch of salt to the hash function to keep users on their toes, like this: http://hg.openjdk.java.net/jdk/jdk/file/e9c11ba790b2/src/java.base/share/classes/java/util/ImmutableCollections.java#l619 (It’s an implementation detail, but for now this combiner would be enough to buy us a better future: `(h,x) -> ((h*31)+x)^SALT`) If we aren’t cautious about this, I’m afraid that users will eventually discover that we are using the Objects.hash algorithm, we will be pressured to document it, and then we’ll be locked out from an easy improvement to records. It’s easier to introduce the salt before that happens. I don’t think we should even promise that the record hashCode is mixed from the hashCodes of the components. That’s TMI, and it boxes us in without telling the user anything useful. All we need to do is promise that a record type’s hashCode fulfills the Object contract, especially relative to the record’s equals method. No other promises, plus a warning that result is subject to change. And then rub some salt on it to keep it clean, as with Set.of and Map.of. — John