ambiguous type inference while working with primitives

Jim Gish jim.gish at oracle.com
Wed May 9 12:39:32 PDT 2012


On 03/06/2012 06:44 PM, maurizio cimadamore wrote:
> Hi
> This error occurs because you have two applicable methods, namely:
>
> *) comparing(IntMapper)
>
> *) comparing(LongMapper)
>
> When there are multiple applicable methods, the compiler tries to
> disambiguate the call-site using a routine called most-specific. The
> goal is to look at the two ambiguous signatures and see if one can be
> considered 'more specific' than the other. For instance, if you have two
> applicable methods, one accepting an Object, and the other accepting an
> Integer, the latter would 'win' as Integer is a subtype of Object.
>
> What's happening in this case is that the compiler doesn't have enough
> information to disambiguate the call-site by just looking at the method
> signatures - that's because IntMapper and LongMapper are two unrelated
> types, so the compiler doesn't know which method to pick - hence the
> ambiguity error.
>
> We are currently exploring the design space, to see if we can allow some
> restricted form of structural subtyping in the most specific algorithm
> (this would allow, i.e. to prefer IntMapper to LongMapper because the
> return type of the IntMapper's descriptor is more specific).
>
> Maurizio
>
> On 06-Mar-12 8:51 PM, Antoras wrote:
>> I get compiler errors due to ambiguous Mapper-objects. I have a class
>> Person which has a method getAge(). If the return value of this method
>> is 'int' the following inline Mapper-object produces an error:
>>
>> Comparator<Person>   c = comparing((Person p1) ->   p1.getAge());
>>
>> If the return type is 'Integer' the above code works.
>>
>> This line:
>>
>> Comparator<Person>   c = comparing(Person::getAge);
>>
>> works neither with 'Integer' nor with 'int';
>>
>> Is this expected behavior or should the type checker recognize that
>> IntMapper is the first one to "choose"?
>>
>>
>> The error message:
>>
>> ListTest.java:203: error: reference to comparing is ambiguous, both
>> method<T#1>comparing(LongMapper<T#1>) in Comparators and method
>> <T#2>comparing(IntMapper<T#2>) in Comparators match
>>        Comparator<Person>   c = comparing((Person p1) ->   p1.getAge());
>>                               ^
>>      where T#1,T#2 are type-variables:
>>        T#1 extends Object declared in method<T#1>comparing(LongMapper<T#1>)
>>        T#2 extends Object declared in method<T#2>comparing(IntMapper<T#2>)
>>
>
I think I have the same problem here:

    StringJoinerTest.java:46: error: reference to mapReduce is
    ambiguous, both method mapReduce(LongMapper<? super
    T>,long,LongBinaryOperator) in Iterable and method
    mapReduce(DoubleMapper<? super T>,double,DoubleBinaryOperator) in
    Iterable match
             int altCompOfStringsLength = lastNames.mapReduce( e ->
    e.length(), 0, (a, b) -> a+b);
                                                   ^
       where T is a type-variable:
         T extends Object declared in interface Iterable
    1 error

So, how does one go about disambiguating this, other than breaking out 
the lambda expressions (and somewhat defeating the point of the 
compactness value).  This, for example, works:

         int stringsLength = lastNames.map(e -> e.length()).reduce(0, 
(a, b) -> a+b);

Thanks,
    Jim





More information about the lambda-dev mailing list