A possible bug in JEP 482: Flexible Constructor Bodies
Alex Buckley
alex.buckley at oracle.com
Mon May 20 23:19:59 UTC 2024
A. To restate in JCK terms: javac conforms to the spec in all three cases.
- Case 1 is legal, and javac compiles it.
- Case 2 is illegal, and javac does not compile it. It's illegal because
the following new rule in 16.9 can't get x to be DA before the instance
initializer:
"V is definitely assigned (and moreover is not definitely unassigned)
before the leftmost instance initializer (8.6) or instance variable
initializer of C iff C declares at least one constructor, every
constructor of C has an explicit constructor invocation, and V is
definitely assigned after every superclass constructor invocation in
these constructors."
- Case 3 is illegal, and javac does not compile it.
B. Because the new 16.9 rule speaks of "every constructor of C has an
explicit constructor invocation", there should be a further test, 2a,
which is the same as 2 but where the body of Q() is an explicit
`super();`. (x would still not be DA after that `super();`.)
C. JEP 482 introduces the notion of an "empty prologue":
An explicit constructor invocation in a constructor body may be
omitted. In this case the prologue is empty, and all the statements in
the constructor body constitute the epilogue.
and the draft JLS relies on the notion in 14.22 and 16.9 ... but AFAICT
the notion isn't actually introduced in the draft JLS 8.8.7.
Alex
On 5/20/2024 3:00 PM, Archie Cobbs wrote:
> Hi Ella,
>
> Thanks for the report.
>
> First, we can dispense with Case 3 - that program doesn't compile under
> any JDK version ("variable x might not have been initialized"), because
> initializer blocks run immediately after super(), which in this case is
> (implicitly) located at the beginning of the constructor and therefore
> prior to the assignment of x.
>
> Having said that, now take a look at Case 2: it has the same problem,
> but in a slightly different form.
>
> You can see this by trying to compile this version of Case 2 with the
> first constructor removed:
>
> class Q {
> final int x;
> int y;
> { y = x; }
> public Q() {}
> }
>
>
> You get the same error "variable x might not have been initialized".
>
>
> When you add back the first constructor to get your original Case 2, you
> still haven't fixed that problem.
>
>
> Then the compiler reports this:
>
>
> Q.java:7: error: variable x might already have been assigned
> this();
> ^
> Q.java:4: error: variable x might not have been initialized
> { y = x; }
> ^
>
>
> The error reported on line 7 is slightly confusing, but it's really just
> a side effect of the error on line 4 that was already present.
>
>
> In other words, clearly someone could invoke the second constructor Q()
> and there would be nothing that initializes field x, so the program is
> not valid.
>
>
> On the other hand, the compiler assumes that the other constructor is
> going to properly initialize all final fields when it sees this(), and
> therefore it deduces that a duplicate assignment must be occurring. This
> assumption is wrong, but only because constructor Q() is invalid.
>
>
> Here's a version that does compile. Note that it fails if you uncomment
> the commented-out line.
>
>
> class Q {
> final int x;
> int y;
> { y = x; }
> public Q(int a) {
> //x = a; // "variable x might already have been assigned"
> this();
> }
> public Q() {
> x = 3;
> super();
> }
> }
>
>
> -Archie
>
>
> On Mon, May 20, 2024 at 4:13 PM Ella Ananeva <ella.ananeva at oracle.com
> <mailto:ella.ananeva at oracle.com>> wrote:
>
> Hi,____
>
> __ __
>
> I found a discrepancy in the behavior of the JEP 482 compiler
> regarding definite assignment of a final non-static blank field in a
> prologue of a constructor:____
>
> Case 1____
>
>
>
> Case 2____
>
>
>
> Case 3____
>
> class Q {
> final int x;
> int y;
> { y = x; }
> public Q(int a) {
> x = a;
> super();____
>
> }
> }____
>
>
>
> class Q {
> final int x;
> int y;
> { y = x; }
> public Q(int a) {
> x = a;
> this();
> }____
>
> public Q() {}
> }____
>
>
>
> class Q {
> final int x;
> int y;
> { y = x; }
> public Q(int a) {
> x = a;
> }
> }____
>
> __ __
>
> Compilation succeeds____
>
>
>
> Compilation fails____
>
>
>
> Compilation fails____
>
> __
>
>
> --
> Archie L. Cobbs
More information about the amber-dev
mailing list