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




Reply via email to