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