-
Bug
-
Resolution: Fixed
-
P4
-
None
Flow scoping allows some pattern variables to flow beyond the statement within which they were declared, e.g.
if (!(e instanceof String s)){
return;
}
System.out.println(s); // s is in scope here
This is specified as follows (JLS 6.3.2.2):
A pattern variable is introduced by `if (e) S` iff (i) it is introduced by `e` when false, and (ii) `S` cannot complete normally.
The intent is that if `S` could not complete normally this enables us to deduce that the only way a statement following the conditional could be reached is if the pattern matched successfully.
Here is a counterexample:
l: if (!(e instanceof String s)) {
break l;
}
System.out.println(s);
JLS 14.22 says this about `break` statements:
- A `break`, `continue`, `return`, `throw`, or `yield` statement cannot complete normally.
So the analysis says that the pattern variable `s` *is* in scope in the
statements that follow the labeled conditional statement, but if `e` does not
evaluate to a `String`, it is possible to reach the print statement
without initializing the pattern variable `s`.
The conditions on `S` must be strengthened to exclude this example. A simple ban
on `S` containing a `break` statement with a label would suffice, but would exclude
acceptable code such as:
l: while (true) {
if (!(e instanceof String s)) {
...
break l;
}
// s in scope here
}
System.out.println(s); // error - s not in scope here
if (!(e instanceof String s)){
return;
}
System.out.println(s); // s is in scope here
This is specified as follows (JLS 6.3.2.2):
A pattern variable is introduced by `if (e) S` iff (i) it is introduced by `e` when false, and (ii) `S` cannot complete normally.
The intent is that if `S` could not complete normally this enables us to deduce that the only way a statement following the conditional could be reached is if the pattern matched successfully.
Here is a counterexample:
l: if (!(e instanceof String s)) {
break l;
}
System.out.println(s);
JLS 14.22 says this about `break` statements:
- A `break`, `continue`, `return`, `throw`, or `yield` statement cannot complete normally.
So the analysis says that the pattern variable `s` *is* in scope in the
statements that follow the labeled conditional statement, but if `e` does not
evaluate to a `String`, it is possible to reach the print statement
without initializing the pattern variable `s`.
The conditions on `S` must be strengthened to exclude this example. A simple ban
on `S` containing a `break` statement with a label would suffice, but would exclude
acceptable code such as:
l: while (true) {
if (!(e instanceof String s)) {
...
break l;
}
// s in scope here
}
System.out.println(s); // error - s not in scope here
- relates to
-
JDK-8302865 Illegal bytecode for break from if with instanceof pattern matching condition
-
- Resolved
-