Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8218940

Clarify treatment of final variables with initializers in switches

    Details

    • Type: Bug
    • Status: In Progress
    • Priority: P4
    • Resolution: Unresolved
    • Affects Version/s: 11
    • Fix Version/s: tbd_major
    • Component/s: specification
    • Labels:
    • Subcomponent:
    • Understanding:
      Fix Understood

      Description

      Test:

      class AssignInSwitch {

          void test(String s) {
              switch (s) {
                  case "a":
                      final int i = 3;
                      final int j; j = 3;
                      break;
                  case "b":
                      i = 4; // error
                      j = 4; // no error
                      break;
              }
          }

      }

      javac allows the variable 'j' to be assigned to in the second case, but not 'i'. Both should be considered definitely unassigned and not definitely assigned at this point, and so the meaning of the name is a variable, not a value (JLS 6.5.6.1), and the assignment should be allowed (JLS 15.26).

      (You can verify that javac considers both variables not definitely assigned by replacing the assignments with variable reads.)

      There are some issues with the spec that should be addressed separately, but I don't think they affect the desired outcome:

      - 6.5.6.1 says a final variable name denotes a value (and so cannot be assigned to) if it is "definitely assigned"; it should say "not definitely unassigned". In unreachable code, where variables are both DA and DU, javac does not (and should not) prevent assignments to blank final variables.

      - The Chapter 16 introduction can be read to mean that the domain of the DU property is blank final variables. So if a variable is not blank final, it can never be DU and denote a variable. But it also says that the symbol V, used in all the rules, "represent[s] a local variable or blank final field which is in scope". In practice, excluding initialized finals mostly makes sense as an optimization, except for this special case in switches—there's not a principled reason that 'i' in my example can't be re-assigned just like 'j'.

      - 16.2.9 says that for a variable to be DU at the start of a block-statement-group, it must be DU after the previous statement (a 'break' here) *and* after the switch target expression—impossible, because the variable isn't in scope. But by the same logic, 'j' is not DU in the second case. Clearly this isn't the intent, nor is it how javac behaves.

        Attachments

          Activity

            People

            • Assignee:
              dlsmith Dan Smith
              Reporter:
              dlsmith Dan Smith
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated: