The interfaces IdentityObject and ValueObject must die !
forax at univ-mlv.fr
forax at univ-mlv.fr
Wed Jan 26 23:36:09 UTC 2022
> From: "daniel smith" <daniel.smith at oracle.com>
> To: "Remi Forax" <forax at univ-mlv.fr>
> Cc: "valhalla-spec-experts" <valhalla-spec-experts at openjdk.java.net>
> Sent: Wednesday, January 26, 2022 4:42:30 PM
> Subject: Re: The interfaces IdentityObject and ValueObject must die !
>> On Jan 26, 2022, at 2:18 AM, [ mailto:forax at univ-mlv.fr |
>> forax at univ-mlv.fr ] wrote:
>>> In other words: I don't see a use case for distinguishing between primitive and
>>> value classes with different interfaces.
>> Primitive classes does not allow nulls and are tearable, following your logic,
>> there should be a subclass of ValueObject named PrimitiveObject that reflects
>> that semantics.
> But this isn't a property of the *class*, it's a property of the *type*, as used
> at a particular use site. If you want to know whether an array is flattened,
> the class of the component can't tell you.
The semantics B1/B2/B3 is a property of the class, an instance of a value class stored in an Object is still an instance of a value class, same for primtive classes.
Being flattenable or not, is an orthogonal concern. Being flattenable for a field or a local variable/parameter it's a property of the descriptor, but for arrays it's a property of the array class because arrays are covariant in Java.
For arrays, a code like this should work
Object[] o = new QComplex;[3];
o[1] = QComplex;.new(...);
>> This is especially useful when you have an array of PrimitiveObject, you know
>> that a storing null in an array of PrimitiveObject will always generate a NPE
>> at runtime and that you may have to use either the volatile semantics or a lock
>> when you read/write values from/to the array of PrimitiveObject.
>> For examples,
>> public void m(PrimitiveObject[] array, int index) {
>> array[index] = null; // can be a compile time error
>> }
> If we said
> primitive class Point implements PrimitiveObject
> then it would be the case that
> Point.ref[] <: PrimitiveObject[]
> and so PrimitiveObject[] wouldn't mean what you want it to mean.
> We could make a special rule that says primitive types are subtypes of a special
> interface, even though their class does not implement that interface. But that
> doesn't really work, either—primitive types are monomorphic. If you've got a
> variable with an interface type, you've got a reference.
I don't understand why you want Point.ref/LPoint; to be a PrimitiveObject and not a ValueObject.
We have QPoint;[] <: LPoint;[] so LPoint; implements ValueObject and QPoint; implements PrimitiveObject.
Anyway, it shows that using interfaces to represent properties of a class (behavior of ==, synchronized, nullability, tearability) is far from obvious.
> Meanwhile, I'd suggest writing the method like this, using universal generics:
> <T> public void m(T[] array, int index) {
> array[index] = null; // null warning
> }
If you are Okay with code that can raise a NPE, why are you not Okay with code that can raise an IllegalMonitorStateException ?
Or said differently why ValueObject and not PrimitiveObject.
I'm not advocating for having 3 interfaces, because i think of the ratio cost/benefit of such interfaces is poor. But having 2 interfaces is definitively weird since we have updated the model to B1/B2/B3.
>> An impossible type, it's a type that can be declared but no class will ever
>> match.
>> Examples of impossible types, at declaration site
>> interface I extends ValueObject {}
>> interface J extends IdentityObject {}
>> <T extends I & J> void foo() { }
> It would definitely be illegal to declare a class that extends I and J. Our
> rules about well-formedness for bounds have always been sketchy, but
> potentially that would be a malformed type variable.
another cost of introducing those interfaces, the JLS has to be updated to take care of the invalid bounds
>>> Abandoning the property entirely would be a bigger deal.
>> If we do not use interfaces, the runtime class of java.lang.Object can be
>> Object, being an identity class or not is a just a bit in the reified class,
>> not a compile time property, there is contamination by inheritance.
> Object can't be an identity class, at compile time or run time, because some
> subclasses of Object are value classes.
Object the type is not an identity class, but Object the class (the Object in "new Object()") is an identity class.
> What you'd need is a property of individual *objects*, not represented at all
> with the class. Theoretically possible, but like I said, a pretty big
> disruption to our current model.
nope, we need to decouple the notion of type from the notion of being an identity/value/primitive class because it's a property of the class not a property of the type.
>> For me, it's like opening the door of your house to an elephant because it has a
>> nice hat and saying you will fix that with scotch-tape each time it touches
>> something.
> Ha. This sounds like maybe there's a French idiom involved, but anyway we should
> try to get John to add this to his repertoire of analogies.
"Like a bull in a china shop" is "comme un éléphant dans un magazin de porcelaine" in French.
Rémi
More information about the valhalla-spec-observers
mailing list