acmp again !

forax at univ-mlv.fr forax at univ-mlv.fr
Wed Feb 20 21:55:14 UTC 2019


----- Mail original -----
> De: "Brian Goetz" <brian.goetz at oracle.com>
> À: "Remi Forax" <forax at univ-mlv.fr>, "valhalla-spec-experts" <valhalla-spec-experts at openjdk.java.net>
> Envoyé: Mercredi 20 Février 2019 21:52:01
> Objet: Re: acmp again !

> 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.

I'm still not sure allowing == when the compiler knows that the operands are value types is a good idea, whatever the semantics of acmp is.

All your examples works BTW if they are declared as reified generics
  var x = new Twople("a", "b");
  x == x // true, will compare the reference "a" and "b" respectively

  var x = new Twople(2, 3);
  x == x // true, will compare 2 and 3 respectively


I think we can agree that no solution will be perfect, you have to pick your poison.
And yes, always returning false is perhaps the lesser evil after all.

Rémi

> 
> 
> 
> 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