JDK-8300691 - final variables in for loop headers should accept updates
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Wed Oct 16 13:56:19 UTC 2024
Hi Archie,
there were several interesting design discussions on the JEP [1] you
have created for this.
An intersting angle we discussed was whether we feel imperative for
loops are special enough to deserve special treatment, or whether this
is the start of a loosening process that will eventually lead to allow
capture for every local variable /value/.
In order to better characterize the nature of the problem we’re dealing
with, it would be great if we could gather some more evidence on how
many “dummy” local variables are introduced for the sole purpose of
being able to capture them in a lambda/inner class. More precisely, a
“dummy” local variable is a local variable that:
* is initialized with the value of some other local variable
o is only referenced inside a capture context (either lambda or
inner class)
(corollary: all “dummy” local variables are effectively-final).
Example:
|int x = ... ... x = ... // reassignment ... int x2 = x; // x2 is
effectively-final ... () -> x2; // x2 is only used here! |
Could you come up with a javac patch that detects such “dummy” variable
declarations and prints a note/warning in the compiler output?
Then we can try to run the modified javac to build the JDK and see how
many warnings are found there. Similarly, we can try the modified
compiler against Maven artifacts (we have some infrastructure to do
that), or against other interesting codebases (perhaps Liam, cc’ed,
might help here?)
Let me know what you think.
Cheers
Maurizio
[1] - https://git.openjdk.org/jdk/pull/21415
On 11/09/2024 00:23, Archie Cobbs wrote:
> 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/20241016/34b333fe/attachment-0001.htm>
More information about the amber-dev
mailing list