ambiguous type inference while working with primitives
maurizio cimadamore
maurizio.cimadamore at oracle.com
Tue Mar 6 15:44:44 PST 2012
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>)
>
More information about the lambda-dev
mailing list