JDK-8242479 : compiler implementation for records (Second Preview)
  • Type: CSR
  • Component: tools
  • Sub-Component: javac
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 15
  • Submitted: 2020-04-09
  • Updated: 2020-06-15
  • Resolved: 2020-05-02
Related Reports
CSR :  
Relates :  
Description
Summary
-------

Several minor bugs and enhancements in the Java Language Specification for the
"Records" feature [JEP 359](https://openjdk.java.net/jeps/359) have been identified, and addressed. The feature will remain a
preview feature for JDK 15.

Problem
-------

As a result of testing, discussion and feedback regarding the "Records" preview
feature, several issues in the JLS have been identified. 


1. In Section 4.12.4 it was erroneously stated that the field corresponding to a
   record component is another kind of variable that is implicitly declared
   `final`. 

2. In Section 8.10.1 it was erroneously stated that the `final` modifier can be
   redundantly applied to record components. 

3. Section 8.10.1: Given the following code, it is not clear from the
   specification whether, when reflecting at runtime, the record component `s`
   would be annotated with the annotation `@MyAnnotation` or not:

  ```
  record R(@MyAnnotation String s) { ... }
  ```

4. In Section 8.10.1 it was erroneously stated that if the declared type of a
   variable arity record component has a non-reifiable element type, then a
   compile-time unchecked warning could be suppressed if the record type is
   annotated with `@SafeVarargs`. 

5. Section 8.10.4: The accessibility of the canonical constructor is required to
   be `public`. This is unexpected and does not align with default constructors
   in normal classes which have the same access modifier as the class. 

6. Section 8.10.4: The following code compiles per the spec (as formal parameter
   names are not part of a method/constructor signature):

 ``` 
    public record R(int i) {
        public R(int j) {  // Different name for formal parameter
            i = j; 
        }
    }
 ```

7. Section 8.10.4: It is not clear if the following code compiles per the spec:

 ```
    public record R(int i...) { // Variable-arity record component
        public R(int[] i) {     // Use array type for component
            i=i;
        }
    }
```

8. Section 8.10.5: The design of compact constructor has been changed to exclude assignment to an instance field. The following definition of a compact constructor compiles
   per the spec and is now an error: 

 ```
    record R(int i) {
        R { this.i = 0; }
    }
 ```

In addition, two design enhancements are proposed:

1. The previous specification treated local record declarations as a special
   case. This caused some confusion (not least because the treatment of nesting
   in the JLS is confusing). It is proposed that the specification is
   refactored to allow more naturally for the local declaration of static types.
   This allows for the new feature of supporting _local enums_ and _local
   interfaces_. 

2. Extend the use of the `@Override` annotation to declare that a method is an
   accessor method for a record component.


Solution
--------

Addressing these issues:

1. Erroneous changes to Section 4.12.4 have been removed.

2. [8.10.1] The `final` modifier can not be applied to record components.

3. [8.10.1] The specification has been clarified to state that annotations on a
   record component only remain on the record component if its
   annotation type is applicable to record components. 

4. [8.10.1] It was clarified that the `@SafeVarargs` annotation has to be
   applied to the _canonical constructor_, not the record type, in order to
   avoid an unchecked warning. 

5. [8.10.4] The specification has been changed such that the accessibility of an
   implicitly declared canonical constructor is the same as that of the record type. If
   the canonical constructor is explicitly declared then its access modifier
   must provide at least as much access at the record type.

6. [8.10.4] The specification now requires the names of record components and
   formal parameters in canonical constructors to be identical.

7. [8.10.4] The specification requires that a formal parameter in a canonical
   constructor must be a variable arity parameter if and only if the
   corresponding record component is a variable arity record component.

8. [8.10.4] The specification now states that assignment to a field
   corresponding to a record component of a record class in
   the body of a compact constructor is a compile-time error.

Addressing the enhancements:

1. A number of changes have to made to support this enhancement:

    - Two new specification documents have been produced: "Consistent Class and
      Interface Terminology" clarifies the usage of terms related to classes and
      interfaces, and more clearly distinguishes them from types; and "Local Static
      Interfaces and Enum Classes" builds on this spec to support local
      interface and enum class declarations.

    - The Records specification now builds on top of the JLS as enhanced by the two
      specification documents described above. 

    - [14.3] The Records specification now extends support of local interfaces and local
      enum classes to additionally support local _records_. 

2. [9.6.4.4] The specification has been enhanced to allow the use of the
   `@Override` annotation to declare that a method is an accessor method for a
   record component. 

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

The updated specification is attached as `records-20200428.zip`. Inside of the `.zip` folder, apart from the specification file (records-jls.html) two other specification documents this specification builds on are included (class-terminology-jls.html) and (local-statics-jls.html). The previous specification, the one used for [JEP 359](https://openjdk.java.net/jeps/359) is also attached as records-jls-20200115.pdf
Comments
Since the semantics is not changing with this clarification, I'm re-affirming the approval of the request.
15-06-2020

[~darcy] I made a minor clarification to the JLS draft. In 8.10.4 I state that "The access modifier of a canonical constructor for a record class must provide at least as much access as the record class" and enumerate the cases, but one is missing, i.e. - If the record class is private, then the canonical constructor may be declared with any accessibility. This has now been added. Revised zip attached.
15-06-2020

[~darcy] I can confirm that there are not changes to the serialization spec. Sorry for missing to comment on that
04-05-2020

Since the serialization document references JEP 359, I assume it is *not* changing for 15. If this is not the case, please clearly indicate what aspects of serialization of records is updated for 15 and re-finalize the CSR. Moving to Approved.
02-05-2020

I have attached a zip file with the last iteration of the spec: records2-20200501.zip. The difference with the previous iteration is that the last specification now states that assignment to a field corresponding to a record component of a record class in the body of a compact constructor is a compile-time error.
01-05-2020

Moving to Provisional.
30-04-2020