Final field update in unreachable for loop update section
Tagir Valeev
amaembo at gmail.com
Sat Feb 17 02:58:25 UTC 2018
Wow, it's so old story! Thanks!
Tagir.
17 февр. 2018 г. 2:20 AM пользователь "Dan Smith" <daniel.smith at oracle.com>
написал:
Yep, I came to the same conclusion independently. Glad you landed there,
too!
There's an old spec bug I was looking at that raised this issue, too.
https://bugs.openjdk.java.net/browse/JDK-4660984
I've closed the javac bug, and proposed some spec changes in JDK-4660984.
—Dan
On Feb 16, 2018, at 3:26 AM, Tagir Valeev <amaembo at gmail.com> wrote:
Hello! Thank you for investigating this. On a second look the javac
behavior looks somewhat logical.
The for loop execution looks like this:
/-----------------------------> (next statement)
|
initialization --> condition --> body -X-> incrementation
^ |
\-----------------------/
Having a "break" statement we removed an edge marked with X. However
there's still an "incrementation->condition->body" chain, even though the
incrementation is unreachable. So javac likely goes along this path and
finds that "x=2" (body) is possible after "x=1" (increment). To my
understanding, usually spec works like this: unreachable statements are
still analyzed. The x is not DU after increment, thus it should not be DU
before empty condition, thus it should not be DU before body. 16.2.12 says:
V is definitely unassigned before the condition part of the for statement
iff all of the following are true:
-
V is definitely unassigned after the initialization part of the for
statement.
-
Assuming V is definitely unassigned before the condition part of the for
statement, V is definitely unassigned after the contained statement.
-
Assuming V is definitely unassigned before the contained statement, V is
definitely unassigned before every continue statement for which the
for statement
is the continue target.
This would be perfectly logical were condition part executed either after
initialization or after body (or continue statement within the body).
However actually it's executed either after initialization or after the
incrementation. Probably this part should be reformulated in the following
way:
V is definitely unassigned before the condition part of the for statement
iff all of the following are true:
-
V is definitely unassigned after the initialization part of the for
statement.
-
Assuming V is definitely unassigned before the condition part of the for
statement, V is definitely unassigned after the incrementation part.
This way it would be aligned with javac implementation and sound more
logical.
Am I missing something?
Regards,
Tagir Valeev.
On Fri, Feb 16, 2018 at 3:39 AM, Vicente Romero <vicente.romero at oracle.com>
wrote:
> Thanks Dan for evaluating this one, certainly this set of rules is tricky
> to follow. I have created bug [1] to track this issue,
>
> Vicente
>
> [1] https://bugs.openjdk.java.net/browse/JDK-8198245
>
>
> On 02/15/2018 03:16 PM, Dan Smith wrote:
>
> Thanks for the interesting test case.
>
> You're pushing on this part of the language spec:
> https://docs.oracle.com/javase/specs/jls/se9/html/jls-16.html#jls-16.2.12
> <https://docs.oracle.com/javase/specs/jls/se9/html/jls-16.html>
> https://docs.oracle.com/javase/specs/jls/se9/html/jls-16.html#jls-16.2.13
>
> On Feb 7, 2018, at 7:49 PM, Tagir Valeev <amaembo at gmail.com> wrote:
>
> public class Sample1 {
> final int x;
>
> Sample1() {
> for(;;x=1) {
> x=2;
> break;
> }
> }
> }
>
>
> An error should only occur if 'x' is assigned to where it is definitely
> unassigned ("DU").
>
> The rules say that:
>
> - x is DU before the for loop
>
> - x is DU after the (empty) initialization
>
> - assuming x is DU before the (empty) condition:
> - x is DU before the loop body*
> - x is DU after the 'break' (because this is unreachable)
> - x is DU after the loop body
>
> - thus, x is DU before the (empty) condition
>
> - x is DU before 'x=2'
>
> - x is DU after the 'break'
>
> - x is DU after the loop body
>
> - x is DU before the incrementation statement
>
> - x is DU before 'x=1'
>
> (*The connection between the start of the condition and the start of the
> loop body is a little confusing in the spec, because when the condition is
> empty, it refers to the initialization instead. But you get the same answer
> either way.)
>
> So, the compiler is wrong: there is no error in Sample1.
>
> public class Sample2 {
> final int x;
>
> Sample2() {
> x=2;
> for(;;x=1) {
> break;
> }
> }
> }
>
>
> No error here, which is fine. 'x=1' is unreachable, so it doesn't matter
> that it performs an assignment.
>
> (You get the same behavior if you do 'if (false) x = 1'.)
>
> —Dan
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20180217/94003e2a/attachment.html>
More information about the compiler-dev
mailing list