JDK-8236189 : local records shouldn't capture any non-static state from any enclosing type
  • Type: CSR
  • Component: tools
  • Sub-Component: javac
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 14
  • Submitted: 2019-12-18
  • Updated: 2020-01-14
  • Resolved: 2020-01-13
Related Reports
CSR :  
Description
Summary
-------

Local records shouldn't capture any non-static state from theirs enclosing type. Both the spec and the implementation should be updated to enforce this.

Problem
-------

Local records should not be allowed to capture any non-static state from any enclosing type

Solution
--------

Fix the mentioned issue in the spec and the implementation

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

The following extra condition has been added to the definition of a local record [14.3]:

    It is a compile-time error if a local record contains a usage of a variable declared in the enclosing block.

Following comments, the definition of a local record now reads as follows (The final sentence is new):

    A local record is a record type declaration (8.10) that is not a member of a class. A local record is implicitly static. A local record is not a local class.

Example 14.3-1 has been clarified that it deals with local classes only.
    
Comments
Changing status from Proposed to Finalized. After the updates by Gavin stemming from discussions outside of the CSR, moving to Approved. The main difference from the initial proposal is to explicitly state that local records are *not* local classes.
13-01-2020

I have added some further clarification around local classes and local records.
13-01-2020

If this behavior were the end of the story, then I would agree that a separate section "Local Records" would be clearer. However, the reality is more subtle. As outlined in https://mail.openjdk.java.net/pipermail/amber-spec-experts/2020-January/001904.html, the terminology surrounding nested constructs, and the restrictions around nested constructs, are ad-hoc and generally a mess, and something we would like to clean up ASAP. In fact, this ad-hoc mess regarding nesting is what caused the current bug -- that we all were focused on the treatment of static vs instance capture, and missed local capture. But it was never the intent for local records to be "inner". We considered several choices as to how to move forward: (a) fix this all at once in 14; (b) fix this all at once in 15, accepting the bad behavior of records in 14; and (c) fixing the most egregious problem now (mistaken capture of locals by local records), and fix the rest in 15. We chose (c) because doing (a) was impractical and doing (b) meant that we would go out with a records feature that did not behave as we intended it, and which would bias the feedback we are seeking by previewing it. The claim in 14.3 that all local classes are inner classes is part of the mess that needs to be cleaned up. Going forward, "local class" will refer solely to nesting, and some local classes will be inner (such as local classes today), some will be explicitly static (declaring a local class with the `static` modifier), and some will be intrinsically static (enums, records, interfaces.) And static-ness will govern both instance variable capture and local capture. There's a clean story we can get to, but this particular issue is just the minimum to bring records in line with its design intent.
13-01-2020

This appears to be a proposed edit to JLS 14.3. "Local Class Declarations." IIRC, elsewhere there are rules to the effect of "unless otherwise stated, records are like classes." As written this update seems to imply that local records are a specialized kind of local class, with some additional constraints. However, JLS 8.1.3. "Inner Classes and Enclosing Instances" states "An inner class is a nested class that is not explicitly or implicitly declared static. " and JLS 14.3 states "All local classes are inner classes." so there all local classes should be neither implicitly or explicitly declared static. Therefore, from my reading of the proposed edit, a local record is *not* a kind of local class, it is a distinct sort of entity with a similar lexical nesting structure, but different rules. If that is the case, local classes would seem to me better handled in a separate section or at least a clear distinction made between the rules for local classes and local records.
13-01-2020

This is the first occurrence of a local construct which cannot capture locals from enclosing constructs. For nested constructs, `static` has only meant "cannot capture `this`", but says nothing about other locals. We need a new term for such a construct besides "static".
02-01-2020