A possible bug in JEP 482: Flexible Constructor Bodies
Gavin Bierman
gavin.bierman at oracle.com
Wed May 22 16:13:06 UTC 2024
Yes, thanks Alex. I will amend the draft JLS doc to explicitly state the possibility of empty prologue/epilogues.
Gavin
On 21 May 2024, at 00:19, Alex Buckley <alex.buckley at oracle.com> wrote:
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> <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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20240522/ec80a882/attachment-0001.htm>
More information about the amber-dev
mailing list