lambda compiler implementation - third milestone
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Sun May 27 04:03:41 PDT 2012
On 27/05/12 10:03, Peter Levart wrote:
> On Thursday, May 24, 2012 04:43:55 PM Maurizio Cimadamore wrote:
>> Dear lambditizens,
> Hello Maurizio,
>
> I have just built the newest lambda jdk and am trying it out.
>
>> in the last few months I've been busy updating the javac infrastructure
>> in the JDK 8 repo [1..10] and then rewrote (after a couple of painful
>> merge rounds ;-)) the type-checking support for lambda/method reference
>> from scratch, leveraging such architectural changes. This resulted in a
>> much more cohesive implementation [11], that closely reflects the
>> direction the language appears to be headed in (see below). There are,
>> of course, few holes and gaps here and there, but, with your help, we'll
>> work towards chasing'em all.
>>
>> One of the most important features supported in this new implementation
>> is the long-awaited generalized support for target-typing in method
>> context - this means that if you call a generic method or pass a diamond
>> in a method context, javac will try its best in order to figure out what
>> the inferred types are. Not all situations are handled, but the obvious
>> ones should work as expected.
The examples you listed are not supported.
My idea of naive is:
m(List<String> ls) { ... }
m(new ArrayList<>)
If you have inference variables on both ends, you have an inference
cycle. Now, since Java overload resolution is a function of argument
types only (the target type of the assignment is only considered at a
later stage), we are not supposed to look into that during overload
resolution.
It's also a problem of whether we want inference to be more global vs.
keeping it local - your case might look reasonable enough - but then
what about:
List<String> ls = m(m(m(m(ArrayList<>))));
Making inference more powerful will make those problems disappear, that
will have other side-effects - for instance the fact that you will get
strange error messages in unexpected places (as the compiler 'delays'
the time at which inference is performed to wait for some constraints).
All these design dimensions are on the table as we speak - for now the
compiler leaves cyclic inferences cases alone, and treats them in a
backward compatible fashion.
Maurizio
> // I have tried 2 basic use cases that someone might naively expect to work:
>
> public class InferTest<T>
> {
> public<C extends Collection<T>> C test0()
> {
> return null;
> }
>
> public<C extends Collection<T>> C test1(C collection)
> {
> return collection;
> }
>
> public<C extends Collection<? super T>> C test2()
> {
> return null;
> }
>
> public<C extends Collection<? super T>> C test3(C collection)
> {
> return collection;
> }
>
> public static void main(String[] args)
> {
> InferTest<String> stringTest = new InferTest<>();
>
> // case 1:
>
> List<String> strings0 = stringTest.test0();
>
> List<String> strings1a = stringTest.test1(new ArrayList<>());
> List<String> strings1b = stringTest.<List<String>>test1(new ArrayList<>());
> List<String> strings1c = stringTest.test1(new ArrayList<String>());
>
> // case 2:
>
> List<String> strings2 = stringTest.test2();
>
> List<String> strings3a = stringTest.test3(new ArrayList<>());
> List<String> strings3b = stringTest.<List<String>>test3(new ArrayList<>());
> List<String> strings3c = stringTest.test3(new ArrayList<String>());
> }
> }
>
>
> ...
>
> The strings0 assignment infers the C of<C>test0() as something that can be assigned to List<String>, so one might expect that such inferred type could be used to infer types in method argument context (left to right), but...
>
> The strings1a assignment fails with:
>
> error: method test1 in class InferTest<T> cannot be applied to given types;
> required: C
> found: ArrayList<Object>
> reason: inferred type does not conform to declared bound(s)
> inferred: ArrayList<Object>
> bound(s): Collection<String>
> where C,T are type-variables:
> C extends Collection<String> declared in method<C>test1(C)
> T extends Object declared in class InferTest
>
> So one must either use strings1b or strings1c to make it work.
>
>
> The other use-case is using a wild-card with "? super T" bound on a nested type parameter. The strings2 assignment infers C of<C>test2() as something assignable to List<String>, but...
>
> The strings3a assignment fails with:
>
> error: incompatible types: ArrayList<Object> cannot be converted to List<String>
>
> So one must use either strings3b or strings3c.
>
>
> Is any of the two use-cases expected to work in the new scheme?
>
> Regards, Peter
>
>> As this is a big revolution in the way in which javac type-checks method
>> calls, there could be some initial hiccups - in order to reduce the
>> chance of regression as much as possible we also put in place a biggie
>> suite of combinatorial test cases [12] - but please, be patient as new
>> bugs might be uncovered.
>>
>> I would like to thank the many of you who provided very valuable
>> feedback and bug reports - please keep it going!
>>
>> Maurizio
>>
>> [1] - http://hg.openjdk.java.net/jdk8/jdk8/langtools/rev/51fb17abfc32
>> [2] - http://hg.openjdk.java.net/jdk8/jdk8/langtools/rev/e28a06a3c5d9
>> [3] - http://hg.openjdk.java.net/jdk8/jdk8/langtools/rev/568e70bbd9aa
>> [4] - http://hg.openjdk.java.net/jdk8/jdk8/langtools/rev/161230ec7c73
>> [5] - http://hg.openjdk.java.net/jdk8/jdk8/langtools/rev/6f0ed5a89c25
>> [6] - http://hg.openjdk.java.net/jdk8/jdk8/langtools/rev/2827076dbf64
>> [7] - http://hg.openjdk.java.net/jdk8/jdk8/langtools/rev/38ae13dcd215
>> [8] - http://hg.openjdk.java.net/jdk8/jdk8/langtools/rev/48ee63caaa93
>> [9] - http://hg.openjdk.java.net/jdk8/jdk8/langtools/rev/d2508136751c
>> [10] - http://hg.openjdk.java.net/jdk8/jdk8/langtools/rev/dda6a5b15580
>> [11] - http://hg.openjdk.java.net/lambda/lambda/langtools/rev/314e550e28af
>> [12] - http://hg.openjdk.java.net/lambda/lambda/jdk/rev/7152aca9aef1
More information about the lambda-dev
mailing list