Overload resolution simplification

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Aug 15 14:56:30 PDT 2013

On 15/08/13 22:36, Zhong Yu wrote:
> On Thu, Aug 15, 2013 at 9:00 AM, Maurizio Cimadamore
> <maurizio.cimadamore at oracle.com> wrote:
>> On 15/08/13 14:24, Zhong Yu wrote:
>>> That is not a reason for Java to reject it too. Java traditionally
>>> does inference based on assignment context; it'll be nice to continue
>>> to do that even with lambda arguments.
>> Well - that wasn't the point of my email; several posts in this thread were
>> of the kind - 'why can't you guys just do what C# does' ?
>> I only tried to show that there are similar limitations elsewhere.
>> I explained at least 3-4 times as to why it is actually a good design choice
>> not to allow stuff as Comparator.comparing overload - but somehow the
>> message doesn't get across. It's not like we are making something dumber or
>> different from what it used to be; it's true Java does inference based on
>> target context - but that inference has _never_ affected the outcome of
>> overload resolution - which helps overload selection to remain tractable
>> (i.e. not NP-hard, to go along with Eric Lippert). We'd like to keep it that
>> way. That means sticking with a design principle that guided us in the past
>> - but I do understand that much of this stuff is subtle and hard to disgest.
>> Maurizio
> I've been only arguing for the limited overload case where all
> overloaded methods must agree upon the parameter types of implicit
> lambda arguments. That is a tractable strategy. In your previous
> example.
>> m(x->g(y->f(...)))
>> where m, g, f are overloads.
> if m,g,f satisfy the requirement about lambda parameter types, it is
> as tractable as
>    m( (X x)->g( (Y y)->f(...) ) )
> If m,g,f don't satisfy the requirement, fail immediately.
> Your other objection is that lambda parameter types may depend on
> method type variables; but it seems to me that we can first infer
> method type variables from other arguments and assignment target,
> after which the lambda parameter types are resolved per method,
> therefore we can check whether all methods agree upon lambda parameter
> types. This is done before selecting the most specific method.
In the complex cases (such as Comparator.comparing) this is almost 
always the case; the lambda parameter type depends on some method type 
Now, if the method type-variable is in a position that doesn't overlap 
with the return type, fine, we could do that (in fact that's how javac 
worked until last week).

If there's an overlap between the return type and that method 
type-variable, then you have two choices:

*) you throw the context into the overload machinery - thus making the 
problem much harder - i.e. in cases like

m(g(x-> ...)) [see below]

*) you throw the context or give up depending on what kind of context is 
- i.e. if assignment context then it's ok [see below]

*) you give up (what javac did)

So, to stress the point I'm making - in a case like this:

SomeTarget s = g(x-> ...)

you have only one target to consider when you do overload selection of 
g. In this case, however:

m(g(x-> ...))

You have multiple targets to throw into the overload selection for g - 
one for each m overload. This means overload resolution grows 
exponentially with the level of nesting.

> This process may be too complex for programmers to follow, which is
> probably Dan's original point. I don't think people care. Nobody reads
> the 40 page long JLS section 15.12, yet people are doing ok based on
> intuition. I believe people's intuition can handle the limited
> overload capability too; in all examples shown so far, none is
> difficult to understand if the method is overloaded and the compiler
> accepts the invocation. It is more difficult to understand why
> overloading does not work in these cases.
The problem is that people (not necessarily users) is gonna need to read 
that JLS section - as they will have to implement IDEs or different 
compilers. Do we want _all_ compilers in the world to sign up for that 
kind of combinatorial explosion? AFAIK none of the IDEs out there (but 
Netbeans, which uses javac itself as a backend) implements the full 
overload/inference check as described in the spec and as was implemented 
in javac - and you know what? People didn't even realized that when 
using them.

> Zhong Yu

More information about the lambda-spec-observers mailing list