Inline Record vs JLS / Reflection
john.r.rose at oracle.com
Wed Dec 16 19:58:06 UTC 2020
On Dec 16, 2020, at 12:39 PM, forax at univ-mlv.fr wrote:
> De: "John Rose" <john.r.rose at oracle.com>
> The last is cleanest; the cost is resolving some technical
> debt in Valhalla, which is allowing more kinds of supers
> for primitive classes. There’s no firm reason, IMO, why
> Record could not be a super of both primitive and identity
> classes, all of which are proper records. Basically we need
> to make interfaces and abstract classes look a little more
> similar, with respect to the requirements of primitive
>> yes, in the case of enum it's more difficult because ordinal and name are fields in java.lang.Enum.
I have a trick up my sleeve for that: Migrate Enum
to be a parametric class, and parameterize the fields.
The effect of this will be to re-allocate them in every
subtype that asserts the parameter. The “raw” version
would continue to behave as today, for compatibility
> Spoiler alert: I think the final solution will endow
> abstract classes with *both* abstract and concrete
> constructors. The former will serve primitive
> classes and the latter will serve identity classes.
> Record will be such an abstract class.
>> By abstract constructors, i suppose you mean empty constructors so they can be bypassed when creating a primitive type.
I mean constructors (<init> methods) which are ACC_ABSTRACT.
(Or some equivalent.) The point is they are not only empty but
have no Code attribute.
>> It will not work with java.lang.Enum.
>> For enums, we need have both constructors and factory methods and a way to ensure that they are semantically equivalent.
You are right about the argument-taking constructors. Something
more is needed there than I have outlined. But I think even that
difficulty is not a blocker. For example, if a primitive class that
inherits from Enum can (somehow) decouple from the name and
ordinal fields of Enum (say, using a specialization trick as above)
then it can probably also assume responsibility for managing its
own name and ordinal values. They could be wired up using
method overrides replacing Enum methods. (Hands waving…)
>> One possibility is to have the VM generating the factory methods code only inside the primitive type from the chain of superclasses, doing the transformation that is currently done by the compiler at runtime.
Yes. A good question is how to formalize such a transformation
using as little “special pleading” as possible, preferably none at all.
>> It can works that way, if i want a primitive enum, the constructor of java.lang.Enum has to be marked as transformable to a factory method, same thing for the constructor of the primitive enum itself.
Marked as transformable, or simply marked as irrelevant.
This is related to a “wish list” item for specialized generics,
which is optional fields and methods. (The “isPresent” field
of an Optional<long> is needed, but not for Optional<String>.)
Today’s Enum constructor could be made optional (using
one pretext or another), and simply ignored for p-Enums.
>> For java.lang.Enum an for any classes of a primitive enum, an empty factory method is generated with a descriptor, an empty body, and an attribute pointing to the corresponding constructor.
>> At runtime, when the class is loaded, the VM insert the correct code in the factory method of the non abstract class.
Or have *both* the factory method *and* classic constructor,
with suitable gating logic about which may be used when.
(This would be a doubling down on the tactic of making
abstract classes supers of *both* p-classes and i-classes.)
>> If the VM generates the code, we are sure that the constructor and the factory method are both equivalent.
We could also trust the author of Enum to certify this.
>> Another solution is to have a special verifying pass that verify that the constructor and the factory method are both equivalent, but it seems harder to me.
At some point, you have to trust a human author.
More information about the valhalla-spec-observers