jsr166y.forkjoin vs closures - ambiguous method reference

Neal Gafter neal at gafter.com
Sun Jul 6 23:44:41 PDT 2008


Mark-

I'm going through the reported issues, and I see I haven't responded to the
enclosed report.

I'm not sure exactly how best to proceed on this issue.  Your suggestion
seems more based on the C++ overload resolution "best match" rules, but
overload resolution doesn't work that way in Java.  Which of several
candidates is most specific is computed without reference to the actual
arguments.

Overload resolution is already a three-pass affair, and I don't relish
adding new passes.  The three passes are (1) no boxing or varargs, (2)
boxing but not varargs, and (3) both boxing and varargs allowed.  One
possibility would be to have the closure conversion be sensitive to the
boxing-allowed/not-allowed phase flag when passed directly as an argument to
a method, which means that there are then two different versions of the
closure conversion.  Another possibility would be to disallow boxing in the
closure conversion for restricted closures, and allow them in unrestricted
closures; this parallels the closest existing language constructs to which
they correspond (i.e. overriding in an anonymous class can't use an unboxed
return type, but you can use a primitive loop index in a for-each loop).

I suspect the right solution is to make the closure conversion sensitive to
the overload resolution pass, but for now I'm just going to acknowledge that
this is an open issue.

Regards,
Neal

On Sat, Nov 24, 2007 at 5:57 AM, Mark Mahieu <mark at twistedbanana.demon.co.uk>
wrote:

> Neal,
>
> Playing with the closures version of jsr166y I've run into something which
> I think should compile, but doesn't.  I've taken the example from the
> javadoc for jsr166z.forkjoin.ParallelArray, and tried to pass closure
> literals into the calls to withFilter() and withMapping():
>
>        import jsr166z.forkjoin.*;
>
>        public class StudentStatistics {
>
>                ParallelArray<Student> students = null;
>                // ...
>                public double getMaxSeniorGpa() {
>
>                        return students.withFilter({Student s => s.credits >
> 90})
>                                        .withMapping({Student s => s.gpa})
>                                        .max();
>                }
>        }
>
>        class Student {
>                int credits;
>                double gpa;
>        }
>
>
> However javac complains about the call to the overloaded withMapping()
> method:
>
>        StudentStatistics.java:10: reference to withMapping is ambiguous,
> both method <V>withMapping({U => V}) in
> jsr166z.forkjoin.ParallelArray.WithMapping<Student,Student> and method
> withMapping({T => double}) in
> jsr166z.forkjoin.ParallelArray.WithFilter<Student> match
>                                .withMapping({Student s => s.gpa})
>                                ^
>        1 error
>
>
> If I explicitly assign my closure literal to a variable of type
> {Student=>double} and pass in that variable instead, it compiles (and
> appears to resolve to the correct method).  A stand-alone test case exhibits
> the same behaviour:
>
>        public class AmbiguousMethodReference {
>
>                public static void main(String[] args) {
>
>                        // this is fine
>                        { => double } fn = { => 2.0 };
>                        foo(fn).exec();
>
>                        // compiler says 'reference to foo is ambiguous'
>                        foo({ => 2.0 }).exec();
>                }
>
>                static <T> Foo<T> foo({ => T } fn) {
>                        return new Foo<T>();
>                }
>
>                static DoubleFoo foo({ => double } fn) {
>                        return new DoubleFoo();
>                }
>
>                static class Foo<T> {
>                        void exec() { }
>                }
>
>                static class DoubleFoo {
>                        void exec() { System.out.println("success"); }
>                }
>        }
>
>
> In this test case, it looks to me as though javac is viewing both
> javax.lang.function.D<null> and javax.lang.function.O<Double,null> as
> equally specific candidate types for the closure literal, but I think what
> I'm wanting is for the compiler to try javax.lang.function.D<null> as the
> more specific type first, and then only if it fails to find a match to fall
> back on javax.lang.function.O<Double,null>.
>
> Incidentally, I also tried an explicit cast but javac doesn't like that at
> all - should casts to function types be valid?
>
>        public class CastToFunctionType {
>
>                public static void main(String[] args) {
>
>                        { => double } foo = ({ => double }) { => 2.0 };
>                }
>        }
>
>
>
> Regards,
>
> Mark
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/closures-dev/attachments/20080706/304fedca/attachment.html 


More information about the closures-dev mailing list