I still do not understand how things are supposed to work :(
Remi Forax
forax at univ-mlv.fr
Mon Jul 4 13:27:48 UTC 2022
Hi all,
i still can not wrap my head on how the model is supposed to work from a user POV.
The guideline seems to be that the value class should be used in API and .val companion should be used in implementation.
I'm confused for mainly two reasons
1. this guideline is very similar to the idea of the container model, you only need .val for fields and arrays so it inherits of the shortcoming of the container model.
2. a .val is a kind of non nullable value class but an instance of a value class non-null by construction is not a .val type.
1. Parameterized type are flattened depending on the type arguments which is is part of the public API
To be flattened, a List or a Stream should have a .val as type parameter but that means that the val companion is clearly part of the public API.
This can not simply be fixed by casting a List<Complex.val> to a List<Complex> after creation because this is not a sound conversion, it introduces spurious NPEs.
And because of inference, the type argument can be propagated from the type of a local variable/parameters, so the idea to confine .val to only the implementation does not seem to work.
2. There are a lot of syntax in Java, where we statically know that the result of an expression is not null but those expression are not typed .val
- "this" should be type as a .val
- new Point() should be typed as a .val (as Brian said)
- Point point ...; point.getClass() should be typed Class<Point.val>.
Does it mean that Point.class should be a val, otherwise point.getClass() == Point.class will not work ?
- the binding of an instanceof with a type pattern (e.g. instanceof Point point) should be a .val
- after seeing a requireNonNull(), an if (value != null), assert value != null, etc the type should be a val
This leads to javac having a full null analysis to determine if a value class can be null or not, something we say we do not want.
Here we are in a hard place, because from the user POV a .val is just a non-nullable value class but for the compiler .val is a full (synthetic) class.
To summarize, i'm sure i'm missing something but from a user POV, i do not see the appeal of this model, because of 1, the rules where to put .val or not, are messy and because of 2 either we will have either a lot of peculiar cases to memorize (cf the list above) or a compiler that will be a hindrance because it will not understand what we will be saying.
Rémi
More information about the valhalla-spec-experts
mailing list