JDK-8296148 : wrong effectively final determination by javac
  • Type: CSR
  • Component: tools
  • Sub-Component: javac
  • Priority: P3
  • Status: Proposed
  • Resolution: Unresolved
  • Fix Versions: 20
  • Submitted: 2022-10-31
  • Updated: 2022-11-10
Related Reports
CSR :  
Description
Summary
-------

The `javac` compiler is not in sync with a section of the language specification. In particular with `JLS 18` section `"§4.12.4 final Variables"`. This provokes that some programs that should be rejected according to the language spec are accepted by `javac`

Problem
-------

`javac` is not in sync with section `§4.12.4` of the `JLS 18` specification. In particular `javac` is accepting as effectively final, variables that are the operand of increment or decrement operators. This provokes that `javac` accepts programs that according to the spec should be rejected. As an example this code:

    for (int i = 0; i < 10; i++) {
        Runnable r = () -> System.out.println(i);   // variable i is NOT effectively final
        break;                                      // even though "i++" is never reached
    }

is being accepted by `javac` when it should be rejected as variable `i` is not effectively final and it is being accessed in the body of a lambda expression.

Solution
--------

Synchronize javac with section `§4.12.4` of the `JLS 18` specification.

Specification
-------------

Of interest for this CSR is section `§4.12.4` of the `JLS 18` specification, titled: `"final Variables"` in particular where it reads:

    • A local variable declared by a statement and whose declarator has an initializer
      (§14.4), or a local variable declared by a pattern (§14.30.1), is effectively final
      if all of the following are true:
        - It never occurs as the operand of a prefix or postfix increment or decrement operator (§15.14, §15.15).

Note
--------------
The patch was ran through a corpus of Java source code, and there was only one project out of ~45000 that failed to compile due to this change.