<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
</head>
<body>
<div dir="auto">Hi</div>
<div dir="auto"><br>
</div>
<div dir="auto">Reading the proposal, it seems John is suggesting to use a translation step, so<span></span></div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="auto"><span style="font-size: 12pt; line-height: normal;">for (final int x = 0; x != 0; x++)</span></div>
<div dir="auto"><span style="font-size: 12pt; line-height: normal;">    System.out.println(x);</span></div>
<div dir="auto"><span style="font-size: 12pt; line-height: normal;">System.out.println("done");</span></div>
<div dir="auto"><br>
</div>
<div dir="auto">Would turn into</div>
<div dir="auto"><br>
</div>
<div dir="auto">for (int x$synthetic = 0; x$synthetic != 0; x$synthetic++) {</div>
<div dir="auto">    final int x = x$synthetic;</div>
<div dir="auto">    System.out.println(x);</div>
<div dir="auto">}</div>
<div dir="auto">System.out.println("done");</div>
<div dir="auto"><br>
</div>
<div dir="auto">Which solves your issue.</div>
<div dir="auto"><br>
</div>
<div dir="auto">However, it doesn't feel like the extra variable is needed?</div>
<div dir="auto"><br>
</div>
<div dir="auto">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.</div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="auto">I don't think that this breaks any existing code. As (non-blank) final variables can't appear in those locations. </div>
<div dir="auto"><br>
</div>
<div dir="auto">Greetings</div>
<div dir="auto">Robbe Pincket </div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div dir="auto"><br>
</div>
<div><br>
</div>
<div id="ms-outlook-mobile-signature" dir="auto">Sent from <a href="https://aka.ms/AAb9ysg">
Outlook for Android</a></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> amber-dev <amber-dev-retn@openjdk.org> on behalf of Archie Cobbs <archie.cobbs@gmail.com><br>
<b>Sent:</b> Wednesday, September 11, 2024 1:23:15 AM<br>
<b>To:</b> amber-dev <amber-dev@openjdk.org><br>
<b>Subject:</b> JDK-8300691 - final variables in for loop headers should accept updates</font>
<div> </div>
</div>
<div>
<div dir="ltr">
<div>I'm curious about this possible future language tweak and have been looking at it more closely:
<a href="https://bugs.openjdk.org/browse/JDK-8300691" target="_blank">https://bugs.openjdk.org/browse/JDK-8300691</a></div>
<div><br>
</div>
<div>I think this would be a nice practical change that fits well within the Amber ambit. However, I'm stuck on one question.<br>
</div>
<div><br>
</div>
<div>To summarize, there are two independent changes being proposed:</div>
<div>
<ol>
<li>Prevent statements in for() loop steps from causing for() loop variables to lose their "effectively final" status</li><li>Allow final for() loop variables to be mutated in the for() step (but not the for() body)</li></ol>
</div>
<div>
<div>Change #1 would allow code like this:</div>
<div><br>
</div>
<div style="margin-left:40px"><span style="font-family:monospace">for (int i = 0; i < 10; i++) {<br>
</span></div>
<div style="margin-left:40px"><span style="font-family:monospace">    Runnable r = () -> System.out.println(i);   // hooray, "i" is effectively final<br>
</span></div>
<div style="margin-left:40px"><span style="font-family:monospace">}</span></div>
</div>
<div>
<div><br>
</div>
<div>
<div>Change #2 would allow code like this:</div>
<div><br>
</div>
<div style="margin-left:40px"><span style="font-family:monospace">for (final int i = 0; i < 10; i++) {<br>
</span></div>
<div style="margin-left:40px"><span style="font-family:monospace">    System.out.println(i);          // we can rest assured "i" can't change in here<br>
</span></div>
<div style="margin-left:40px"><span style="font-family:monospace">}<br>
</span></div>
<br>
</div>
<div>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.<br>
</div>
<div><br>
</div>
<div>For example, these two examples do not compile:</div>
<div><br>
</div>
<div style="margin-left:40px"><span style="font-family:monospace">final int x = 0;</span></div>
<div style="margin-left:40px"><span style="font-family:monospace">while (x != 0)</span></div>
<div style="margin-left:40px"><span style="font-family:monospace">    System.out.println(x);         // error: unreachable statement<br>
</span></div>
<div style="margin-left:40px"><span style="font-family:monospace">System.out.println("done");</span></div>
<div><br>
</div>
<div>
<div style="margin-left:40px"><span style="font-family:monospace">final </span><span style="font-family:monospace">int x = 0;</span></div>
<div style="margin-left:40px"><span style="font-family:monospace">while (x == 0)</span></div>
<div style="margin-left:40px"><span style="font-family:monospace">    System.out.println(x);</span></div>
<div style="margin-left:40px"><span style="font-family:monospace">System.out.println("done");        // error: unreachable statement</span></div>
<div><br>
</div>
<div>We shouldn't expect the equivalent for() statements to compile either, and in fact today they don't:<br>
</div>
</div>
<div style="margin-left:40px"><br>
</div>
<div style="margin-left:40px"><span style="font-family:monospace">for (final int x = 0; x != 0; )<br>
    System.out.println(x); </span><span style="font-family:monospace">        // error: unreachable statement</span><br>
<span style="font-family:monospace">System.out.println("done");</span></div>
<div><br>
</div>
<div style="margin-left:40px"><span style="font-family:monospace">for (final int x = 0; x == 0; )<br>
    System.out.println(x);<br>
System.out.println("done");</span><span style="font-family:monospace">        // error: unreachable statement</span></div>
<div><br>
</div>
<div>
<div>
<div>But now suppose we add a step, which Change #2 would newly allow:<br>
</div>
</div>
<div style="margin-left:40px"><br>
</div>
<div style="margin-left:40px"><span style="font-family:monospace">for (final int x = 0; x != 0; x++)<br>
    System.out.println(x); </span><span style="font-family:monospace">        // error: unreachable statement... ?</span><br>
<span style="font-family:monospace">System.out.println("done");</span></div>
<div><br>
</div>
<div style="margin-left:40px"><span style="font-family:monospace">for (final int x = 0; x == 0; x++)<br>
    System.out.println(x);<br>
System.out.println("done");</span><span style="font-family:monospace">        // NOT an unreachable statement</span></div>
<div><br>
</div>
<div>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.<br>
</div>
</div>
<div>
<div><br>
</div>
<div>Alternatively, the compiler could change its behavior to never consider final loop variables as constant expressions, but this could break existing code.<br>
</div>
<br>
<div>Of course, if Change #2 had too many issues, Change #1 would still be useful on its own.<br>
</div>
<div><br>
</div>
<div>Thoughts?<br>
</div>
<br>
</div>
<div>Thanks,<br>
</div>
<div>-Archie<br>
</div>
</div>
<div><br>
<span class="x_gmail_signature_prefix">-- </span><br>
<div dir="ltr" class="x_gmail_signature" data-smartmail="gmail_signature">Archie L. Cobbs<br>
</div>
</div>
</div>
</div>
</body>
</html>