acmp again !

Brian Goetz brian.goetz at
Wed Feb 20 20:52:01 UTC 2019

Yes, it's a tempting direction.  John and I both walked that road, in 
the hope that there was a reasonable place to cut off the regress.  (And 
we both walked back disappointed.)

One problem is that with erased generics, all Ts become Object:

     /* erased */ value class Box<T> {
         T t;

translates to

     value class Box {
         Object t;

So no two boxes would be == to each other -- in fact, a given Box would 
not be == to itself.  I think users would find

     Optional<Point> o = Optional.of(p);
     o == o // false

to be surprising!  Similarly, classes like

     value record Twople<T,U>(T t, U u);

     Twople<String, String> x = new Twople("a", "b"),
          y = x;
     x == x // false
     x == y // false

Whereas the non-generic version:

     value record TwoStrings(String a, String b);

     TwoStrings x = new TwoStrings("a", "b"),
         y = x;
     x == x  // true
     x == y  // true

So I think what this does is just move the surprise to where you don't 
trip over it 100% of the time, but you still trip often enough that you 
curse it.

On 2/20/2019 3:33 PM, Remi Forax wrote:
> I still think we have not finished exploring how to implement acmp for value types.
> We currently have two semantics for value types:
> - always return false,
> - recursively compare each components
> Support of acmp like the support of synchronized or System.identityHashcode is not a part of the original model where we can just say, it should work like an int because it's a consequence of lworld, making value types subtypes of Object, not something inherent to the concept of value types. or said differently, if it should work like an int, a == on value types at Java level should be converted to a vcmp (like there is an icmp_*) which is not an answer to how acmp is supposed to work.
> The issue with the first semantics is that it will be very surprising and will not be compatible with all the existing codes that only use == instead of a == followed by a call to equals().
> The issue with the second semantics is that it's an unbounded computation, shaking the Java performance model everybody has in mind by moving == from one of the fastest operation to a potentially very slow operation.
> I wonder if there is not a intermediary semantics, return false if one field is an Object or an interface or do a component wise comparison otherwise ?
> For value types like Point, Complex, == is the component wise comparison, for a value type that works like Optional, == return false.
> It seems not that bad but it means that doing an == on a wildcard of a reified generics like Atomic<T> depends on the class of T at runtime ?
> Rémi

More information about the valhalla-spec-observers mailing list