heads-up: biggie overload rewrite

Sam Pullara spullara at gmail.com
Thu Jul 25 11:15:22 PDT 2013


I just did a build this morning and still see these fail:

        Comparator<String> comparator = Comparator.comparing(String::length);
        Comparator<String> comparator = Comparator.comparing(s -> s.length());

Are they still supposed to result in:

java: reference to comparing is ambiguous
  both method <T>comparing(java.util.function.ToLongFunction<? super T>) in java.util.Comparator and method <T>comparing(java.util.function.ToDoubleFunction<? super T>) in java.util.Comparator match

Sam

On Jul 25, 2013, at 9:47 AM, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:

> Dear lambdians,
> I've just pushed a patch [1] that enhances javac overload 
> resolution/most specific story in several ways. One of the most notable 
> effects is the removal of the dreaded 'inference loop' message [2]. The 
> logic behind that message was noble: at the time we thought it would 
> have been better to report an error when the compiler was forced to 
> infer a variable to some 'default' instantiation (such as j.l.Object), 
> as this could cause severe downstream problems when type-checking a 
> lambda whose body depended on that choice. However, this was before we 
> added the more complex inference support; now that we have a more 
> capable inference engine, with all bells and whistles, we also have a 
> bigger degree of complexity and, because inference constraints are 
> propagated transitively, the line between default and non-default 
> instantiation has become a lot fuzzier than it used to be. Hence the 
> decision of getting rid of that logic (and related error message) - 
> which also makes the language more consistent (as inference typically 
> only gave such errors when lambdas/method references are present).
> 
> Other improvements in sight for the structural most specific logic; many 
> of you [3,4,5] have reported cases in which the compiler was unable to 
> distinguish between several signatures, where the 'right' choice seemed 
> indeed really easy. The problem in that case was that the structural 
> most specific check would only kick in if the compiler can prove that 
> all target types agree on the parameter types to be inferred for i.e. an 
> implicit lambda. In certain cases (when generic methods were used), the 
> compiler couldn't do that, so it basically went back to the old most 
> specific logic. Here's an example:
> 
> <T,R> Stream<R> map(Stream<T> s, Function<T,R> f) { }
> <T> IntStream map(Stream<T> s, ToIntFunction<T> f) { }
> 
> map(ss, s->s.length()); //now ok - used to be ambiguous
> 
> There are rules to this game though; if the variable to be inferred to 
> be able to type-check the lambda (T in the above example) happened to 
> depend on one of the inference variables mentioned in the method return 
> type, the most specific check would fail and the compiler would again 
> report an ambiguity. The reason for this is that it's not possible to 
> guarantee that the eager instantiation of T would remain the same after 
> looking at the target type (and we want overload selection to be 
> independent from the target type, as we believe it's crucial to keep the 
> model tractable for developers).
> 
> The last improvement is related to the way in which method arguments are 
> type-checked; javac is now able to reason about the subtle dependencies 
> that arise when a lambda is passed as an argument to a generic method; 
> in the above case for instance, javac will detect that there's a 
> dependency between T and R in the first method. In fact, if we had an 
> instantiation for T, we would then be able to type-check the lambda and 
> we will most likely be able to derive new constraints for R. So, it 
> would be mad for the compiler to go and try to infer R _before_ looking 
> at the lambda expression.
> 
> I think those improvements go a long way in terms of polishing the 
> overall overload resolution story that the language presents to 
> developers; it gets rid of several outstanding issues, and makes the 
> whole overload selection process more streamlined and consistent. I'm 
> looking forward to hear your feedback (and bug reports :-)) as you start 
> using the next promoted lambda bits.
> 
> Enjoy the ride!
> 
> [1] - http://hg.openjdk.java.net/lambda/lambda/langtools/rev/d34073d069c8
> [2] - 
> http://mail.openjdk.java.net/pipermail/lambda-dev/2013-July/010352.html
> [3] - 
> http://mail.openjdk.java.net/pipermail/lambda-dev/2013-July/010476.html
> [4] - 
> http://mail.openjdk.java.net/pipermail/lambda-dev/2013-June/010088.html
> [5] - 
> http://mail.openjdk.java.net/pipermail/lambda-dev/2013-July/010590.html
> 
> Maurizio
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 



More information about the lambda-dev mailing list