JDK-8236894 : (IGNORE) Changes to Records specification
  • Type: CSR
  • Component: specification
  • Sub-Component: language
  • Priority: P3
  • Status: Closed
  • Resolution: Withdrawn
  • Fix Versions: 14
  • Submitted: 2020-01-09
  • Updated: 2020-01-13
  • Resolved: 2020-01-13
Related Reports
CSR :  
Description
Summary
-------

After the record's spec was released as several internal and external contributors have reported several bugs or clarification issues that should be fixed in the spec

Problem
-------

The reported issues include:

 - names of formal parameters in canonical constructors must match the name of the corresponding record component
 - local records should not be allowed to capture any non-static state from any enclosing type
 - the 'final' modifier shouldn't be allowed to be redundantly applied to record components
 - clarify the interaction between records and @SafeVarargs annotation

Solution
--------

Fix the mentioned issues in the spec

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

    @@ -2230,14 +2230,14 @@
     
     #### **8.10.1 Record Components** {#jls-8.10.1}
     
     The _record components_ of a record type, if any, are specified by a list of
    -comma-separated parameter specifiers in the header of a record declaration.
    -Each record component consists of a type (optionally preceded by the `final`
    -modifier and/or one or more annotations) and an identifier (optionally
    -followed by brackets) that specifies the name of the record component. If a
    -record type has no record components, then the record header consists of an
    -empty pair of parentheses.
    +comma-separated parameter specifiers in the header of a record declaration. Each
    +record component consists of a type (optionally preceded by one or more
    +annotations) and an identifier (optionally followed by brackets) that specifies
    +the name of the record component. If a record type has no record components,
    +then the record header consists of an empty pair of parentheses.
     
    @@ -2250,14 +2250,15 @@
     
     *RecordComponent*:
    -: { *VariableModifier* } *UnannType* *VariableDeclaratorId*
    +: { *Annotation* } *UnannType* *VariableDeclaratorId*
     : *VariableArityRecordComponent*
     
     *VariableArityRecordComponent*:
    -: { *VariableModifier* } *UnannType* { *Annotation* } `...` *Identifier*
    +: { *Annotation* } *UnannType* { *Annotation* } `...` *Identifier*
     
     > It can be seen that the production for *RecordComponent* is identical in
    -> content to the production for *FormalParameter* ([8.4.1]).
    +> content to the production for *FormalParameter* ([8.4.1]), except a record
    +> component can not have a `final` modifier.
    @@ -2279,10 +2280,6 @@    
    -It is permitted for a record component to redundantly specify the `final`
    -modifier. It is a compile-time error if `final` appears more than once as a
    -modifier for a record component.
    -
     A record component may be a variable arity record component, indicated by an
     ellipsis following the type. At most one variable arity record component is
     permitted for a record type. It is a compile-time error if a variable arity
    @@ -2316,9 +2313,9 @@
     
     If the declared type of a variable arity record component has a non-reifiable
     element type ([4.7]), then a compile-time unchecked warning occurs for the
    -declaration of the variable arity record component, unless the record type is
    -annotated with `@SafeVarargs` ([9.6.4.7]) or the warning is suppressed by
    -`@SuppressWarnings` ([9.6.4.5]).
    +declaration of the variable arity record component, unless the canonical
    +constructor ([8.10.4]) is annotated with `@SafeVarargs` ([9.6.4.7]) or the
    +warning is suppressed by `@SuppressWarnings` ([9.6.4.5]).
     
     :::
     
    @@ -2480,8 +2477,8 @@
     If a canonical constructor is explicitly declared, then it must additionally
     satisfy the following conditions; otherwise a compile-time error occurs:
     
    -- The types of the formal parameters in the formal parameter list of the
    -canonical constructor must be identical to the declared type of the
    +- The names and types of the formal parameters in the formal parameter list of the
    +canonical constructor must be identical to the names and declared type of the
     corresponding record component.
     
     - A canonical constructor must not be generic ([8.8.4]).
    @@ -2567,12 +2564,16 @@     
    -In a record type _R_, the signature of a compact constructor declaration is
    -the derived constructor signature of _R_ ([8.10.4]).
    -
    -> Unlike constructors in records, and indeed in classes in general, no explicit
    -> formal parameter list is given for a compact constructor, but is derived from
    -> the record component list.
    +In a record type _R_, the formal parameter list for a compact constructor
    +declaration is implicitly declared and taken from the derived constructor
    +signature of _R_ ([8.10.4]).
    +
    +More precisely, in a record type _R_, the signature of a compact constructor
    +declaration is the derived constructor signature of _R_ ([8.10.4]).
    +
    +> This means that given a record type with a record component named *c*, in the
    +> body of compact constructor an occurrence of an unqualified name *c* denotes
    +> the implicit formal parameter *c*.
     
     It is a compile-time error to declare more than one compact constructor
     declaration for a record type.
    @@ -2587,7 +2588,8 @@
     
     - The compact constructor must be declared `public`.
     
    -- The body of a compact constructor must not contain a `return` statement ([14.17]).
    +- The body of a compact constructor must not contain a `return` statement
    +  ([14.17]).
     
     - The body of a compact constructor must not contain an explicit constructor
     invocation statement ([8.8.7.1]).
    @@ -2904,7 +2906,8 @@
         applicable to local variable declarations or type contexts.
     
     -  **a record component but *T* is not applicable to record component
    -declarations, field declarations, method declarations, or type contexts.**
    +   declarations, field declarations, method declarations, formal and exception
    +   parameter declarations, or type contexts.**
     
    @@ -3595,8 +3598,41 @@
     
     All local classes are inner classes ([8.1.3]).
     
    -**A *local record* is a record type declaration ([8.10]) that is not a member of
    -a class. A local record is implicitly `static`.**
    +:::inserted
    +
    +A *local record* is a record type declaration ([8.10]) that is not a member of
    +a class. A local record is implicitly `static`.
    +
    +It is a compile-time error if a local record contains a usage of a variable
    +declared in the enclosing block. 
    +
    +> Local records are constrained with regards to with variables they can access.
    +> The fact that a local record is implicitly `static` means that it is a
    +> compile-time error if a local record uses a non-`static` member of an
    +> enclosing class. It is permitted to use a `static` member of an enclosing
    +> class. Here is an example to illustrate the constraints. 
    +> 
    +> ```java
    +> class LocalRecordTest {
    +>     static int si;
    +>     int nsi;
    +> 
    +>     void m() {
    +>         int li;
    +> 
    +>         record R(int r) {
    +>             void print() {
    +>                 System.out.println(si);  // ok, static member of enclosing class
    +>                 System.out.println(nsi); // error, non-static member
    +>                 System.out.println(li);  // error, local variable
    +>             }
    +>         }
    +>     }
    +> }
    +> ```
    +
    +:::
    +
     
     Every local class declaration statement is immediately contained by a block
     ([14.2]).
Comments
The spec has been updated at http://cr.openjdk.java.net/~gbierman/jep359/latest and the zip of this spec is attached
10-01-2020