[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