ambiguous type inference while working with primitives

maurizio cimadamore maurizio.cimadamore at
Tue Mar 6 15:44:44 PST 2012

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).


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:
> 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>)

More information about the lambda-dev mailing list