Vararg records and canonical constructor

Tagir Valeev amaembo at
Mon Dec 23 16:08:35 UTC 2019


Two samples:

record Test(int[] args) {
  public Test(int... args) {
    this.args = args;


record Test(int... args) {
  public Test(int[] args) {
    this.args = args;

Both are accepted by javac (14-ea+27-1339). In both cases, record
component varargness is ignored and canonical constructor varargness
is taken into account upon record object instantiation. However, I'm
not quite sure that this is expected behavior. I feel it would be more
logical, were compiler reject such records.

It looks like javac behavior aligns with the current spec draft [1]:

> The types of the formal parameters in the formal parameter list of the canonical constructor must be identical to the declared type of the corresponding record component.

Looking into 8.10.1 I see:

> If the record component is a variable arity record component, then the declared type is an array type specified by 10.2.

So we can conclude that the record component declared as `int... args`
and formal parameter declared as `int[] args` have identical type
`int[]`, so no compilation error should occur. Still, this looks too
permissive. Once we declare a canonical constructor, record component
varargness completely loses its meaning. Also looking into the record
header alone, one cannot say whether it's possible to use varargs to
construct a record instance, because it's possible that the canonical
constructor exists and it overrides the varargness. I feel that the
spec should add one more restriction to canonical constructors, e.g.:

- If the record component is a variable arity record component, the
corresponding canonical constructor formal parameter must be a
variable arity parameter and vice versa.

What do you think?

With best regards,
Tagir Valeev


P.S. And happy holidays to everybody who has holidays!

More information about the amber-spec-experts mailing list