Notes on implementing concise calls to constructors with type parameters

Maurizio Cimadamore Maurizio.Cimadamore at Sun.COM
Wed May 13 09:49:34 PDT 2009

I'm working at the implementation of the coin item 'concise calls to 
constructors with type parameters'[1][4]. I've been following the 
previous emails about this subject and I noted that the proposed 
implementation strategy is essentially to mimick the diamond notation by 
providing synthetic factory methods. As already noted[2] this approach 
has some complications:

* Generic constructors that declare their own type variables
* accessibility modifiers
* var-args
* boxing/unboxing conversion

I came out with an alternate implementation[3] strategy which makes use 
of the javac's ForAll type:

*) When a call to a constructor exploiting the diamond operator is found 
(e.g. new ArrayList<>()) the type of the new expression should be a 
ForAll - in this particular example, a type F type where the F.tvars = E 
(type variable declared by ArrayList) and where F.qtype = ArrayList<E>.

*) When javac checks the new expression actual type against the expected 
type E (e.g. List<String>) simply re-use Infer.instantiateExpr(F, E), 
where F is the ForAll type calculated as above and E is the expected 
type. Javac will apply in order to infer all the type 
variables in F exploiting (i) info about the expected type E and (ii) 
type-variables (non -recursive) declared bounds. In this very simple 
case javac will infer E to be String and the 'new' expression would 
type-check without problems.

This approach has the advantage of not requiring additional synthetic 
code/type/symbol to be generated on the fly by javac.

The main difference between my implementation strategy and the proposed 
one (exploiting synthetic factory methods) is that my implementation 
performs only a single round of inference, in particular the one 
described in JLS3; the implementation strategy requiring 
synthetic factory methods is slightly more powerful as it can run a full 
inference round (JLS3 followed by In terms of Java 
code this means that, given the following code:

class Foo<X> {
Foo(X x) { ... }

Foo<?> foo = new Foo<>("Hello!");

my implementation infers Foo<Object> while an implementation through 
static factories will be able to infer Foo<String> (because it would 
take into account inference from actual constructor parameters as well).



More information about the coin-dev mailing list