[External] : Re: RFR: 8194743: Compiler implementation for Statements before super() [v14]
Alex Buckley
alex.buckley at oracle.com
Mon Sep 25 18:25:52 UTC 2023
On 9/25/2023 10:13 AM, Archie Cobbs wrote:
> > An explicit goal of JEP 447 is **any existing program must compile to
> > the same bytecode**. So if we adhere to that goal, local classes
> > declared in pre-construction contexts must have outer instances.
> I don't see this explicit goal stated in JEP 447. There's a sentence
> about compilation in Testing -- "We will compile all JDK classes using
> the previous and new versions of the compiler and verify that the
> resulting bytecode is identical." -- but that sounds merely like a
> nice-to-have property, and one which holds only for JDK classes.
>
> You're right.. the stated goal is actually "Do not change the behavior
> of any existing program."
>
> Making sure the emitted bytecode matches is just one way to accomplish
> that goal (and possibly overkill).
Goals: (always the hardest single section of a JEP to write, BTW)
- Re: "In constructors, allow statements that do not access ..." -- this
Goal basically repeats the Summary in stating the solution. That's not
quite what a Goal is meant to do. The term "initialization logic" is
also a bit wonky because it can be read as dealing with initialization
of the current instance, which is the one thing you can't do before
super/this. The Goal should be: "Give developers greater freedom in
expressing the behavior of a constructor, allowing more natural
placement of logic that currently must be factored into static methods
or into arguments to super(..)." I am not sure that
statements-before-super allow logic which previously was "simply
impossible to express."
- Drop "Correct an error in the specification which defines constructor
invocations as a static context." Spec issues don't drive features.
- Re: "Preserve existing safety and initialization guarantees for
constructors." -- This sounds good but I bet 99% of readers couldn't
enumerate an "existing safety guarantee" if you demanded one from them.
Please spell out if this is about, say, guaranteeing that constructors
still run in top-down order. Also, please also avoid "initialization",
because you are not talking about the initialization of a class (see JLS
12.4) but rather the instantiation of a class.
- Re: "Do not change the behavior of any existing program." -- stated
more fully, this goal is "Perfect source compatibility: Any existing
source code, if recompiled, is legal and has unchanged behavior."
However, that could be a goal of almost any new language feature, so we
don't usually state it. And if we cast things in terms of bytecode --
"Do not change how existing source code is compiled to a class file" --
then it sounds pretty esoteric. I'd drop this goal.
> Thanks - so yes that central question remains... how should we treat
> local classes in pre-construction contexts?
>
> The current implementation answers this question "they are inner classes
> with outer instances just like they would be in any other non-static
> location".
>
> Admittedly that answer was chosen in part because it is the most
> conservative change (in particular, it produces the same bytecode).
>
> But OK let's be a little bolder and ask what would be the BEST change?
>
> My latest thinking is we should just allow local classes to be declared
> "static".
>
> Then "class Local" gives the current behavior (always having an outer
> instance in a non-static context), while "static class Local" gives the
> same behavior as a static member class.
This is a big language change that I'm not going to comment on. You
should review the discussion around JEP 384 about how local record
classes were made implicitly static, never explicitly static.
> Here's a program that tries to instantiate a Local which observes x
> with
> a value other than 5. What does the JLS say about the program?
>
>
> JLS says this()/super() have to be "top level", so they can't be inside
> a try { } block.
>
> What does javac do?
>
>
> Test.java:10: error: switch expression does not have any result expressions
> this(switch (0) { default -> throw new Exception(); });
> ^
> Test.java:12: error: cannot reference this before supertype constructor
> has been called
> new Local(); // Legal or illegal?
> ^
> Test.java:10: error: calls to this() not allowed here
> this(switch (0) { default -> throw new Exception(); });
> ^
> 3 errors
Oops, yes. So, can you guarantee, in the JEP, that a non-static local
class declared in the pre-construction context can never access
enclosing state?
Alex
More information about the compiler-dev
mailing list