on implementing state components as a first class concept
Joe Darcy
joe.darcy at oracle.com
Fri Apr 26 18:04:46 UTC 2019
Hello,
On 4/25/2019 1:26 PM, Brian Goetz wrote:
> To be clear, you are not suggested having two _fields_ in the class file, right? You are only talking about the JLM view of the world?
>
> For class file translation, fields, constructors, and methods are derived members, so we want to preserve everything about the declaration of the records somewhere, most likely an attribute that captures component names, signatures, annos, etc.
>
> So what you are suggesting is that in the JLM view, a record is seen as having two kinds of “class variables”, one set of fields and one set of “state components.”
>
> That we would end up distorting the translation of the fields to use a different name (even though this is an implementation detail) to avoid JLM issues suggests “tail wagging dog” to me.
>
> If the goal is that JLM clients should see record components as such, then perhaps we should expose records as a different kind of top level entity?
Records are a new kind of type and state components are a new kind of
entity to model. There are some precedents in the javax.lang.model API
for how these could be handled. Those precedents guided the initial
javax.lang.model API design previously described on the list [1].
Quoting one point from that discussion:
"To avoid introducing a new top-level element category interface (like
variable, type, package, module), state components are regarded as a new
kind of VariableElement, a name-type pair with other ancillary
information possibly available too." [1]
Unpacking this design choice a bit, it would certainly be technically
possible in javax.lang.model to have a new StateComponentElement
interface (and visitor method, etc.) that would be be sort of element
whose kind was STATE_COMPONENT. This scale of JLM update was done for
modules. Modules were a much larger language change of course and that
scope of change seemed unnecessary as a first-cut at records and their
state components.
If the primary way to think of records is "records are special kinds of
classes built around their state components" then the state components
should be prominent in the model of record. This led to the
getStateComponents method and STATE_COMPONENT ElementKind. The closest
analogue to this situation is enum constants to an enum ("enum types are
special kinds of classes built around their enum constants"). The
TypeElement interface does *not* have a "getEnumConstants" method.
Instead, the constants can be found by iterating over the enclosed
elements and checking for a kind of ENUM_CONSTANT.
For an enum type, the compiler mostly "just" adds two mandated methods,
valueOf(String name) and values(), and the constants are a pretty
direct mapping to public static final fields, as discussed in the manual
way to code the pattern before the language feature. (There is more work
in serialization and uses of enums in switch statements, etc.) For
records, by default the compiler makes more entities per component:
* parameter of a constructor
* same-named accessor method
* private field
* usage in equals/hashCode/toString methods
so I thought a more prominent existence for "state component" as opposed
to "just a private field" was called for. It would also be possible to
do more or less what the implementation does now where the fields are
marked with a kind of STATE_COMPONENT rather than FIELD. The conceptual
question is then are the state components just fields with special
handling or are they something that gets turned into fields (and methods
and parameters...)? If they are just fields, the STATE_COMPONENT kind is
still needed and the method on TypeElement could be dropped. Especially
when reading a record from a class file, I think some indication will be
needed state component versus normal instance field since I would
suspect compilers (and potentially programmers at some point) will find
a need for instance fields beyond just the state components.
HTH,
-Joe
More information about the amber-dev
mailing list