> From: "daniel smith" <daniel.sm...@oracle.com> > To: "Remi Forax" <fo...@univ-mlv.fr> > Cc: "valhalla-spec-experts" <valhalla-spec-experts@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:fo...@univ-mlv.fr | >> fo...@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