JSR 335 Lambda Specification, 0.9.0

Dan Smith daniel.smith at oracle.com
Mon Jan 13 15:12:34 PST 2014


On Jan 7, 2014, at 3:22 PM, Stephan Herrmann <stephan.herrmann at berlin.de> wrote:

> (all this is about 18.5.2:)
> 
> From the Changelog of 0.9.0:
>> Added rules to invocation type inference to special-case when the return type is an inference variable, and may end up either being wildcard-parameterized or requiring unchecked conversion.
> 
> These changes are causing regressions in our implementation.
> I might have some other bugs lurking around, but could you please double check:
> Could some occurrences of R θ be intended to say R instead? Specifically these:
> - bullet 3.2: "Otherwise, if R θ is a parameterized type ..."
> - bullet 3.3: "Otherwise, if R θ is an inference variable α ..."

Yes.  All this means is that the type has inference variables in it.  (R, before substitution, is the declared return type of the method.)

> Additionally the use of erasure in bullet 3.1 causes grief.
> In experiments I do get better results using a raw type instead.

?  Which raw type?

This isn't really new, but simply clarifying/preserving the rule from 15.12.2.6 that, if unchecked conversion occurred, the return type is the erasure.  (See JLS 7.)

> Finally: it would be extremely helpful if you could give examples for
> the new bullets 3.3.1 and 3.3.2. So far I haven't a clue :)

<R> R m(R... args);
<T> void forEach(List<T> arg);

Bullet 3.3.1:

I noticed there's an error: bullet 3.3 should say that U is the _capture of_ the instantiation of alpha.  Here are two examples:

forEach(m((List<?>) null));

Let 'r' and 't' be inference variables.  Bounds B2 for m are { List<?> <: r, r <: Object }.  It would be incorrect to assert that r -> List<t> -- in reality, the constraint is that the _capture of_ 'r' is a subtype of List<t>.  So in this situation we eagerly resolve r = List<?>, perform capture, and then proceed with List<#CAP> -> List<t>.

forEach(m((ArrayList<Readable>) null, (LinkedList<Runnable>) null));

Bounds B2 for m are { List<Readable> <: r, List<Runnable> <: r, r <: Object }.  Again, an error would occur if we required r -> List<t>, but there's no problem if we use lub to resolve r = List<?> and perform capture.

Bullet 3.3.2:

forEach(m((ArrayList) null));

Bounds B2 for m are { List <: r, r <: Object }.  There would be an error if we asserted r <: List<t>.  But if we eagerly resolve r = List, then we can do ArrayList -> List<t> and 18.2.2 can do its job by recognizing an unchecked conversion.

—Dan


More information about the lambda-spec-experts mailing list