Method invocation applicability rules confusion
Chris Dennis
chris.w.dennis at gmail.com
Mon Dec 11 14:59:06 UTC 2017
Forgive me, it’s too long since I was at university, and then I was a physicist, so I just pretended to be good at mathematics/computer science. My intuitive understanding says that f(Consumer<T>, T>) shouldn't be considered applicable given the argument types (as per 15.12.2.3 https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.3 <https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.3>). I’ve tried (and will continue to try) to work through the logic of that section and the accompanying details in Chapter 18, but if you could confirm that it is applicable then that would be great (at least then I’d know that what I’m doing is an academic exercise, and that I should end up proving the method is applicable).
Thanks,
Chris
> On Dec 8, 2017, at 4:39 PM, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:
>
> This is a tricky one - I'll try to explain what's happening :-)
>
> FIrst, let's leave lambdas on the side - this has nothing to do with it. And also simplify the program as follows (I've also alpha-renamed the type vars):
>
> static <T> void f(Consumer<T> c, T o) { }
>
> static <Z> void f(Consumer<Z> c, String s) { }
>
>
> And consider the following invocation:
>
> f(null, null)
>
> Now, looking at the available signatures, one might be tempted to conclude that the second signature is most specific. But that's not how the rules in JLS 15.12.2.5 work - those rule say that we need to do two applicability tests:
>
> 1) is f(Consumer<T>, T) applicable given argument types { Consumer<Z>, String } ?
> 2) is f(Consumer<Z>, String) applicable given argument types { Consumer<T>, T } ?
>
> If the answer is yes to either (1) or (2), that that's the most specific method; if (1) and (2) are both true/false then the callsite is ambiguous.
>
> So, let's process the two questions:
>
> For (1) we have the following applicability tests (note that _only_ Z acts as an an inference variable in this test)
>
> Consumer<T> <: Consumer<Z>
> T <: String
>
> now, no matter what we infer for Z, T<: String is always going to be false. So (1) is not satisfied. Let's move on to (2).
>
> For (2) we have the following applicability tests (this time _only_ T acts as an inference variable)
>
> Consumer<Z> <: Consumer<T>
> String <: T
>
> This looks more interesting. From the first constraint we derive:
>
> Z = T
>
> But this means that, if we incorporate bounds,
>
> String <: T, T = Z --> String <: Z
>
> Which is, again, false.
>
> So, unfortunately, both applicability tests (1) and (2) fails, so neither method is more specific. Hence the ambiguity error.
>
> Cheers
> Maurizio
>
>
>
>
> On 08/12/17 17:34, Chris Dennis wrote:
>> Hi All,
>>
>> I’ve hit an interesting issue with an API that I am responsible for whereby the equivalent to the following does not compile:
>>
>> public class TargetTypingWeirdness {
>>
>> public static void test() {
>> Consumer<String> stringConsumer = System.out::println;
>>
>> f(stringConsumer, o -> o.toString());
>> }
>>
>> static <T> Runnable f(Consumer<T> c, T t) {
>> return () -> c.accept(t);
>> }
>>
>> static <T> Consumer<Object> f(Consumer<T> c, Function<Object, T> ft) {
>> return o -> c.accept(ft.apply(o));
>> }
>> }
>>
>> with:
>>
>> TargetTypingWeirdness.java:9: error: reference to f is ambiguous
>> f(stringConsumer, o -> o.toString());
>> ^
>> both method <T#1>f(Consumer<T#1>,T#1) in TargetTypingWeirdness and method <T#2>f(Consumer<T#2>,Function<Object,T#2>) in TargetTypingWeirdness match
>> where T#1,T#2 are type-variables:
>> T#1 extends Object declared in method <T#1>f(Consumer<T#1>,T#1)
>> T#2 extends Object declared in method <T#2>f(Consumer<T#2>,Function<Object,T#2>)
>> TargetTypingWeirdness.java:9: error: incompatible types: cannot infer type-variable(s) T
>> f(stringConsumer, o -> o.toString());
>> ^
>> (argument mismatch; String is not a functional interface)
>> where T is a type-variable:
>> T extends Object declared in method <T>f(Consumer<T>,T)
>> 2 errors
>>
>> I’m trying to figure out if this is an allowed behavior under the spec, or a bug in javac?
>>
>> Any help greatly appreciated,
>>
>> Chris
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20171211/d0a8cc82/attachment.html>
More information about the compiler-dev
mailing list