Value type hash code

John Rose john.r.rose at
Wed Apr 11 21:54:47 UTC 2018

On Apr 11, 2018, at 2:35 PM, forax at wrote:
> De: "John Rose" <john.r.rose at>
> À: "Remi Forax" <forax at>
> Cc: "Brian Goetz" <brian.goetz at>, "valhalla-dev" <valhalla-dev at>
> Envoyé: Mercredi 11 Avril 2018 23:01:18
> Objet: Re: Value type hash code
> On Apr 11, 2018, at 11:27 AM, Remi Forax <forax at <mailto:forax at>> wrote:
> in the l-world, you can have a reference or a value type in 'a' local,
> so acmp is defined as an identity check (if there is a value type on the left or on the right operand the result is false) not a substitution check.
> Not quite true:  We are currently defining literal acmp on a value to return false always.
> That's to avoid having to buy the whole contract of detecting substitutability.
> so acmp != substitutability, no ?

Correct.  I'd rather keep the symmetry at that point between references and values,
but It seems to a forced move because value substitutability check is not O(1).

> The performance model requires a new user-visible operator to test for the
> "thicker" concept of value substitutability.
> and value substitutability can not be used for implementing equals because equals takes an Object as parameter while the thicker value substitutability is only define for different values of the same value type.

If I understand your point, I already covered it by pointing out that the contract
of (invokespecial) Object.equals does not need to be identical with the contract
of acmp/op==, because Object.equals can be defined by fiat to include a special
path for values, to use something other than acmp/op==.

Should it have this extra path?  Probably.  But you could imagine Object.equals
returning false always for value types, just like acmp/op==.  What it comes down
to is we have at least three concepts to distribute among the legacy operations,
whatever their names may be:

- object identity check (O(1), legacy acmp/op==)
- substitutability (same as identity check *but only for object references*)
- deep equality (including ad hoc definitions specific to classes)

Which bucket should (invokespecial) Object.equals go in, for values?
I think the second, not the first, better matches up with the intended uses
of Object.equals, even though it doesn't match with the *current implementation*
of Object.equals which is acmp/op==.
>  Meanwhile, reference substitutability has always been just a "thin" pointer compare.
> You can say we have generalized substitutability which return false for value type or is a pointer comparison when you have reference,

Not so much generalized, as (say) "object substitutability", which returns false, etc.

> or you can say, we have only identity check for reference, so it returns null for value.


> Apart the fact that the name is different, it's the same thing, and i prefer identity check because it avoid to use the term of "thicker" value substitutability.

Good, I adopted that term in my three-way list above.

Do you still think Object.equals must do object identity checks, or can it do
substitutability for values?  Which aspect of the legacy pointer compare is more
important, for Object.equals:  The fact that it is O(1) or the fact that it detects

— John

More information about the valhalla-dev mailing list