On Dec 16, 2020, at 12:39 PM, [email protected] wrote: > > De: "John Rose" <[email protected]> > > 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 > classes. > >> 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 reasons. > 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. — John
