codeconsole opened a new pull request, #3091:
URL: https://github.com/apache/groovy/pull/3091

   The type checker narrowed a variable after any `instanceof` check on it, for 
the rest of the statement or condition, wherever the check was. Under 
`@CompileStatic` that compiled code that fails:
   
   ```groovy
   @CompileStatic
   String f(CharSequence cs) { 'x' + (cs instanceof String) + cs.length() }
   f(new StringBuilder('ab'))  // ClassCastException
   
   @CompileStatic
   int h(Object x) { if ((x instanceof String) == false) { return x.length() }; 
0 }
   h(42)                       // ClassCastException
   
   @CompileStatic
   int g(Object x) { while (x instanceof String) { break }; x.length() }
   g(42)                       // ClassCastException
   ```
   
   Three commits:
   
   - An instanceof check now narrows only where its outcome guards what 
follows: the condition of an `if`, `while`, `assert` or conditional expression, 
an operand of `&&`, `||` or `!` there, and an operand of `&&` or `||` anywhere. 
In `foo(cs instanceof String, cs.length())`, `[cs instanceof String, cs]` or 
`(cs instanceof String) == cs.isEmpty()`, the later `cs` is no longer taken for 
a `String`. The right operand of `&` no longer sees the narrowing of the left 
one; both still apply after the `&`.
   - A comparison of a check with a boolean literal, on either side, with `==`, 
`!=`, `===` or `!==`, narrows like the check when it is true exactly when the 
check is (`== true`, `!= false`), and like `!(check)` otherwise. Before, `== 
false` narrowed its own branch to `T`, so the second example compiled and 
failed; it is now a compile error, as with `!`, and the else branch and the 
code after an `if` that returns are narrowed. An assigned check, a check cast 
to `boolean`, and the condition of a classic `for` loop keep narrowing as they 
did.
   - The condition and the body of a `while`, `do`/`while` or classic `for` 
loop get their own scope of temporary type information, as the branches of an 
`if` do: the condition narrows in the loop and no longer after it. Assignments 
in the loop still cancel, after it, what an enclosing check told about the 
variable.
   
   Code that relied on the narrowing outside a guard stops compiling. In each 
such case, it compiled to a cast that fails for the other types.
   
   ## Tests
   
   `TypeInferenceSTCTest.testInstanceOf30`, `testInstanceOf31` and 
`testInstanceOf32`, also run statically compiled, fail without the change. 
11,630 tests in the `groovy`, `gls`, `bugs` and STC/SC packages pass, apart 
from six `@Grab` tests that pass on rerun. The Checkstyle and CodeNarc gates 
pass.
   
   The loop and `== false` cases fail in 4.0.33, 5.0.8 and 6.0.0; the first 
example compiles and runs in 4.0.33 and fails in 5.0.8 and 6.0.0.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to