Updated Draft specs for JEP 359 (Records)

Alex Buckley alex.buckley at oracle.com
Mon Nov 4 19:09:03 UTC 2019


Florian,

Thanks for drawing attention to this part of the spec:

On 11/2/2019 3:21 AM, Florian Weimer wrote:
> Is it allowed to declare a canonical constructor explicitly and make
> it non-public?  I think the naswer is no.  But it's not quite obvious
> from the spec, I think.

JLS 8.10.4 defines a "canonical" ctor to be a public ctor whose formal 
parameter list is identical to the record header. If you explicitly 
declare a ctor whose formal parameter list is identical to the record 
header, but you do not make it public, then you have not declared a 
"canonical" ctor. You have declared a ctor that, by virtue of its 
signature, prevents an implicitly declared canonical ctor from being 
declared. This is so unfortunate that it deserves an error message, and 
you will get one.

However, you are right that the spec is slightly misworded. It says "It 
is a compile-time error if a record declaration contains a canonical 
constructor declaration that is not public." but a "canonical" ctor is 
public by definition. It should say "It is a compile-time error if a 
record declaration contains a constructor declaration whose formal 
parameter list is identical to the record header of R, but which is not 
public."

An alternative approach: JLS 8.10.4 could define a "canonical" ctor as 
follows: "Every record type R has a _canonical_ constructor, which is a 
constructor [note the silence on accessibility] whose formal parameter 
list is identical to the record header of R." ... and deem an implicitly 
declared canonical ctor to be public. Then, the compile-time error can 
be left alone, though I would reword it for clarity and for tonal 
agreement with '[exp|imp]licitly declared': "If a canonical constructor 
is explicitly declared, then it must be public, or a compile-time error 
occurs."

The alternative approach is best because the sense of "canonical" is 
dominated by the signature -- just look at javac's error message 
"canonical record constructor must be public" which assumes that 
canonical-ness is obvious (signature-driven) and that the access 
modifier is a separate thing, so to speak. That seems a pretty natural 
view of things for the JLS to embody.

(Sidebar: Why allow a compact ctor declaration to be non-public, when we 
control its grammar that could be hard-coded to use `public`?)

(Sidebar: The compact ctor declaration should be introduced at the same 
time as "A canonical constructor can be explicitly declared ...". I 
recall privately discussing the flow of this section but can't find it 
easily. I suggest that 8.10.4 should be "Canonical Constructor of a 
Record" and that the sole non-canonical clause "A record declaration may 
contain constructor declarations." should live in 8.10.2 "Record Body" 
(not plural; yes, the title of 8.9.2 should drop the D-word too, which 
will happen auto-magically) ... 8.10.2 already says "may contain 
constructor and member declarations" but that opening paragraph should 
advertise the compact ctor's role in helping to initialize the member 
[because otherwise CompactConstructorDeclaration goes unexplained] ... 
the line will be hard to write and this mail is already long enough.)

Alex


More information about the amber-dev mailing list