Notes on implementing concise calls to constructors with type parameters

Neal Gafter neal at gafter.com
Wed May 13 10:52:33 PDT 2009


I should add that the ForAll type doesn't exist in the JLS, so the
specification will have to be done using general type inference. Once it is
done that way, the fact that the argument types are ignored in type
inference will seem quite strange.

On Wed, May 13, 2009 at 10:47 AM, Neal Gafter <neal at gafter.com> wrote:

> Maurizio-
>
> When I discussed the proposed implementation (and specification) strategy
> with Joe Darcy, I did NOT propose to actually generate any code for
> synthetic static factories.  Rather, the strategy is for the compiler to *imagine
> *the existence of a static method *for the purposes of type inference only
> *.  The method would not be added to the class or otherwise preserved in
> the resulting class file or internal symbol table.  Once type inference is
> done, these synthetic methods are discarded.  As you know, symbols and types
> are lightweight objects that are created and discarded frequently by the
> compiler, so this strategy is not likely to introduce any extraordinary
> performance overhead.
>
> In the rare case of generic constructors, the synthetic factory method
> would have additional type parameters for the constructor's own type
> parameters.  There are some subtle issues in handling syntax like
>
> *new <String> Name<>()
> *
>
> but those issues arise in any strategy.  Accessibility and var-args can
> similarly be copied from the underlying constructor.
>
> I agree that your technique has almost the same effect as the one I
> proposed, except that you fail to use the constructor arguments as input to
> type inference.  I consider that a severe disadvantage.  It will result in a
> continued need for static factory methods just to get type inference.
>
> Cheers,
> Neal
>
>
> On Wed, May 13, 2009 at 9:49 AM, Maurizio Cimadamore <
> Maurizio.Cimadamore at sun.com> wrote:
>
>> Hi
>> 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 15.12.2.8 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 15.12.2.8; the implementation strategy requiring
>> synthetic factory methods is slightly more powerful as it can run a full
>> inference round (JLS3 15.12.2.7 followed by 15.12.2.8). 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).
>>
>> Maurizio
>>
>> [1]
>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html
>> [2]
>> http://mail.openjdk.java.net/pipermail/coin-dev/2009-March/000075.html
>> [3] http://cr.openjdk.java.net/~mcimadamore/6840638/webrev.0/<http://cr.openjdk.java.net/%7Emcimadamore/6840638/webrev.0/>
>> [4] http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6840638
>>
>>
>



More information about the coin-dev mailing list