Draft Spec for Second Preview of Flexible Constructor Bodies (JEP 482)
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Mon Jun 10 09:24:15 UTC 2024
Hi Archie,
your comment captures exactly the kind of things I'm worried about.
We basically have classes which have no enclosing instances, but where
enclosing members can be accessed (via other means).
The solution is, for the JLS to define what's accessible and what's not,
in any given scope.
But this leaves javac (and other compilers) to wrestle with the
specifics on how this is actually translated, and, due to the
non-uniformity, the complexity explodes in our face.
Historically, the JLS used to treat this/super calls as a static context
(8.8.7.1). And then JLS also used to say that inner classes defined in a
static context had no enclosing instance (8.1.3).
So, for this particular JEP, I think there's a choice in front of us:
* do we keep JLS as is (and fix javac to do what the spec has always
said the behavior was) ?
* or, do we keep javac as is and then tweak the JLS to model what the
implemented behavior is?
The latter path seems to have been chosen. Do we have a feeling that
local classes in pre-construction context will be radically more common
than they are today? Or are there other reasons behind this decision?
Perhaps the tacit understanding was that "javac got this right", but
looking at the increasing numbers of bugs filed recently in this area,
and after looking more at how the code works, it seems that javac
doesn't have a very principled way to get there, and it is in fact
rather easy to come up with examples which defeats javac's translation
strategy.
> Regardless, when looking at the compiler code, there's many mentions
> of "enclosing instances" and "outer instances" but it's easy to have
> the wrong assumption in your head about what these terms actually mean.
>
> In an ideal world we would all agree to use some standard,
> non-ambiguous terminology, e.g.:
>
> * The phrasing should always be "enclosing instance with respect to
> D", where D is some lexically enclosing class.
> * For a class C, the "enclosing instance of C with respect to D" is
> /defined/ if:
> o D is a class (not interface, record, enum, etc.)
> o C is nested within D
> o There is no static class (or interface, record, enum, etc.)
> declaration between C and D (including C itself)
> * For a class C, the "enclosing instance of C with respect to D" is
> /accessible/ at some point X in C if:
> o The enclosing instance of C with respect to D is defined
> o X is not in an early construction context of D
> * If C is nested directly within D with no intermediate classes,
> then "enclosing instance of C with respect to D" is also "the
> immediately enclosing instance of C".
>
>
I agree this is confusing and we need better terminology. But I'm having
trouble with the model that A is an enclosing instance of B, but A's
members are not accessible in B. I understand why the spec does this -
but it would be vastly simpler (at least from an implementation
perspective) then to say that A is not in fact an enclosing instance of
B, but that B still has some other enclosing instance (some enclosing
class of A). A model such as this would inform the translation strategy
quite clearly. In fact, I'm starting to think if we really want to go
down the path of non-static local classes in pre-construction contexts,
then javac should do things this way regardless of how things are
specified, as that will make the translation strategy more uniform and
less buggy than the one we have today.
Maurizio
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-experts/attachments/20240610/c76302cc/attachment.htm>
More information about the amber-spec-experts
mailing list