JDK-8300691 - final variables in for loop headers should accept updates

Robbe Pincket robbepincket at live.be
Wed Sep 11 05:09:10 UTC 2024


Hi

Reading the proposal, it seems John is suggesting to use a translation step, so


for (final int x = 0; x != 0; x++)
    System.out.println(x);
System.out.println("done");

Would turn into

for (int x$synthetic = 0; x$synthetic != 0; x$synthetic++) {
    final int x = x$synthetic;
    System.out.println(x);
}
System.out.println("done");

Which solves your issue.

However, it doesn't feel like the extra variable is needed?

If we just add a clause in 4.12.4 that says that if the variable is declared in a for loop header and appears as the left side of an assignment or compound assignment or as the argument of a postfix/prefix increment/decrement operator, it isn't considered to be a constant variable.


I don't think that this breaks any existing code. As (non-blank) final variables can't appear in those locations.

Greetings
Robbe Pincket




Sent from Outlook for Android<https://aka.ms/AAb9ysg>
________________________________
From: amber-dev <amber-dev-retn at openjdk.org> on behalf of Archie Cobbs <archie.cobbs at gmail.com>
Sent: Wednesday, September 11, 2024 1:23:15 AM
To: amber-dev <amber-dev at openjdk.org>
Subject: JDK-8300691 - final variables in for loop headers should accept updates

I'm curious about this possible future language tweak and have been looking at it more closely: https://bugs.openjdk.org/browse/JDK-8300691

I think this would be a nice practical change that fits well within the Amber ambit. However, I'm stuck on one question.

To summarize, there are two independent changes being proposed:

  1.  Prevent statements in for() loop steps from causing for() loop variables to lose their "effectively final" status
  2.  Allow final for() loop variables to be mutated in the for() step (but not the for() body)

Change #1 would allow code like this:

for (int i = 0; i < 10; i++) {
    Runnable r = () -> System.out.println(i);   // hooray, "i" is effectively final
}

Change #2 would allow code like this:

for (final int i = 0; i < 10; i++) {
    System.out.println(i);          // we can rest assured "i" can't change in here
}

Change #1 is straightforward but Change #2 raises an issue. A final initialized variable is not only immutable but also can be a constant expression, and this affects reachability analysis.

For example, these two examples do not compile:

final int x = 0;
while (x != 0)
    System.out.println(x);         // error: unreachable statement
System.out.println("done");

final int x = 0;
while (x == 0)
    System.out.println(x);
System.out.println("done");        // error: unreachable statement

We shouldn't expect the equivalent for() statements to compile either, and in fact today they don't:

for (final int x = 0; x != 0; )
    System.out.println(x);         // error: unreachable statement
System.out.println("done");

for (final int x = 0; x == 0; )
    System.out.println(x);
System.out.println("done");        // error: unreachable statement

But now suppose we add a step, which Change #2 would newly allow:

for (final int x = 0; x != 0; x++)
    System.out.println(x);         // error: unreachable statement... ?
System.out.println("done");

for (final int x = 0; x == 0; x++)
    System.out.println(x);
System.out.println("done");        // NOT an unreachable statement

In the first example, the inner statement is still unreachable, so it's OK for the compiler to still report that error, but in the second example, the final statement is now obviously reachable, so the compiler must  do something different. Moreover it would be doing something different based on inspection of the step for mutations to "x", which seems like "spooky action at a distance" and could be spec-challenging.

Alternatively, the compiler could change its behavior to never consider final loop variables as constant expressions, but this could break existing code.

Of course, if Change #2 had too many issues, Change #1 would still be useful on its own.

Thoughts?

Thanks,
-Archie

--
Archie L. Cobbs
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20240911/ac9f0024/attachment.htm>


More information about the amber-dev mailing list