Overload resolution simplification

Ali Ebrahimi ali.ebrahimi1781 at gmail.com
Thu Aug 15 15:21:32 PDT 2013


Hi Maurizio,

On Thu, Aug 15, 2013 at 5:00 PM, Maurizio Cimadamore <
maurizio.cimadamore at oracle.com> wrote:

>  Here's an example in C# that features similar problems as the
> Comparator.comparing case (I beg your mercy for my horrible C# skills :-)):
>
> class Test<T>
> {
>     delegate object Delegate1<X>(X s);
>     delegate string Delegate2<Y>(Y s);
>
>     static Test<Z> m<Z>(Delegate1<Z> d1) { return null; }
>     static Test<Z> m<Z>(Delegate2<Z> d2) { return null; }
>
>     static void test()
>     {
>         Test<string> ts = m((x)=>"");
>     }
> }
>
> We have two overloads, each accepting a slightly different delegate; the
> two delegates are generic (like our comparing SAMs) and they differ only in
> the return type - Delegate2 has a more specific return type. Both methods
> return a Test<Z>, where Z is the same type-variable used to parameterize
> the delegate. If I compile this with my crappy mono compiler I get:
>
> Test.cs(11,27): error CS0411: The type arguments for method
> `Test<T>.m<Z>(Test<T>.Delegate1<Z>)' cannot be inferred from the usage. Try
> specifying the type arguments explicitly
>

This is because C# does not do assignment context inference.
But:
Test<string> ts = m<string>((x)=>"");


> Which seems to be in sync with my understanding of Eric's posts. You need
> to supply another argument to unblock inference for the lambda body;
> otherwise the body won't be used. I.e. this works:
>
> class Test<T>
> {
>     delegate object Delegate1<X>(X s);
>     delegate string Delegate2<Y>(Y s);
>
>     static Test<Z> m<Z>(Delegate1<Z> d1, Z z) { return null; }
> //additional param here
>     static Test<Z> m<Z>(Delegate2<Z> d2, Z z) { return null; }
> //additional param here
>
>     static void test()
>     {
>         Test<string> ts = m((x)=>"", ""); //additional actual here
>     }
>
This is currently fails in java.

Don't get me Wrong. If you have in mind I said we can learn from C# not
copy it as C# learned (even copy) from java in past.
So my intend is combination of current java solution (assignment context
inference which C# does not support) and C#'s one (lambda return type
inference).

We type check lambda body only if all its input type arguments already
inferred from inference context:
    static class Test<T>{
        Comparator<String> m(){
            return Comparator.comparing(t -> t.length()); [1]
        }

        static <P> void m(Comparator<P> c, P t){
            return;
        }

        void m(Comparator<T> c){
            return;
        }

        void test() {
            new Test<String>().m(Comparator.comparing(t -> t.length()));
[2]
            ((Comparator<String>)Comparator.comparing(t ->
t.length())).toString(); [3]
            Comparator<String> c = Comparator.comparing((String x) -> 0);
[4]
            m(Comparator.comparing((t) -> t.length()),""); [5]
        }
    }

For overloaded methods we act in multiple phases.
phase1: we do type check lambda without boxing, unboxing and widening in
return type.
if we get only one overload that successfully type checks lambda So
inference has been succeed, otherwise go phase 2.

phase2: we do type check lambda without boxing and unboxing but with
widening in return type. if we get only one overload that successfully type
checks lambda So inference has been succeed, otherwise go phase 3.

phase3: we do type check lambda with boxing, unboxing and widening in
return type. if we get only one overload that successfully type checks
lambda So inference has been succeed, otherwise ERROR.


One note:
My intention is only to improve and modernize java. java is my all day
work.

Regards,
Ali Ebrahimi


More information about the lambda-spec-observers mailing list