dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.26k stars 1.58k forks source link

Clarify the identityHashCode documentation #41454

Open jamesderlin opened 4 years ago

jamesderlin commented 4 years ago

The last part of the identityHashCode documentation says:

This hash code is compatible with identical.

Exactly what does that mean?

My first interpretation was that the identityHashCode values for two objects would be equal if-and-only-if the two objects were identical, but after some empirical observations, it seems that identityHashCode values are equal if two objects are identical but that non-identical objects may have the same identityHashCode. Since the identityHashCode of an int seems to always be itself, a trivial way to generate a collision is:

void main() {
  String s = 'Hello world';
  int i = identityHashCode(s);

  print(identical(s, i)); // Prints: false
  print(identityHashCode(s) == identityHashCode(i)); // Prints: true
}

Granted, I probably should have expected this since the function has "hash code" in its name, but I think that the identityHashCode documentation could state this explicitly. Compare to the documentation for Object.hashCode which is much more thorough:

Hash codes must be the same for objects that are equal to each other according to operator ==....

Objects that are not equal are allowed to have the same hash code...

(Or maybe there is a 1:1 correspondence with identical for objects of the same type? Ultimately what I'd like is the equivalent of printf("%p", somePointer) in C so that I can tell from logging whether two objects separated in time are the same instance.)

jamesderlin commented 3 years ago

I'm still curious whether identityHashCode is guaranteed to generate different values for different objects of the same type.

lrhn commented 2 years ago

It's not guaranteed to generate different values for different objects.

It can't. There are more different possible objects of class A { final int a, b; A(this.a, this.b); } than there are integers that identityHashCode can return. (Well, in practice I guess there won't be that many instance in a single program, but identityHashCode does not promise to provide unique values. I don't know if it does in practice, but it never promised to.)

It's really a silly sentence to begin with.

It means that if identical(a, b) then identityHashCode(a) == identityHashCode(b), which is ... largely trivial if it behaves like a function. The one indirect consequence is that the identity hash code is stable over time. That might be worth stating.

So, basically, identityHashCode assigns a random integer to each object, which is stable over time, and which is not guaranteed to be unique. And Object.hashCode returns the identityHashCode of the object.