Possible Bug in javac resolving method references.
Dan Smith
daniel.smith at oracle.com
Wed Oct 8 22:58:20 UTC 2014
I think javac is behaving correctly.
To clarify what's going on, there are two methods that must be resolved: 'of' and 'exec'. Since the target type of 'Main::exec' can, in general, influence the resolution of 'exec', the compiler must resolve 'of' _first_.
The resolution of 'of' is allowed to use a little bit of readily-available information about 'Main::exec', but not much. Specifically, 'Main::exec' is categorized as an "inexact" method reference, because it is overloaded (JLS 15.13.1). For simplicity, all inexact method references are treated the same when they appear as arguments to another method: an 'of' candidate is "potentially-applicable" if the method reference is "potentially compatible with" a targeted functional interface type (15.12.2.1). After that, the argument is not considered "pertinent to applicability", so no further checking is done prior to overload resolution (15.12.2.2).
Putting it simply, the types appearing in the signature of the 'exec' methods are irrelevant to the resolution of 'Consumers.of'.
So:
Is 'Main::exec' potentially compatible with WriterConsumer? Yes, WriterConsumer has 2 arguments, and a Main.exec method exists that takes 2 arguments.
Is 'Main::exec' potentially compatible with OutputStreamConsumer? Yes, OutputStreamConsumer has 2 arguments, and a Main.exec method exists that takes 2 arguments.
Are 'Consumers.of(OutputStreamConsumer)' and 'Consumers.of(WriterConsumer)' potentially-applicable? Yes. Are both methods applicable? Again, yes, because there are no arguments that we can type-check during overload resolution.
Hence, ambiguity error.
One can imagine a world in which a method reference is "exact" if the named method is overloaded, but all candidate target types (OutputStreamConsumer, WriterConsumer) have the same arity, corresponding to only one referenced method ('Main.exec(Object,Appendable)'). And if the method reference were exact, its types could be used for disambiguation. But this is not the way it was specified (and is more complex then we'd like, even if it might more closely match a reader's intuition).
The second error ("cannot be applied") is unhelpful, and might be a problem with javac's error reporting, if somebody wants to investigate that.
—Dan
On Oct 5, 2014, at 4:57 AM, taichi sato <ryushi at gmail.com> wrote:
> Hi, I wrote code the below.
>
> https://gist.github.com/taichi/f676381bd148bd497106
>
> javac says me below
>
> src\example\Main.java:13: error: reference to of is ambiguous
> Consumers.of(Main::exec);
> ^
> both method of(OutputStreamConsumer) in Consumers and method of(WriterConsumer) in Consumers match
> src\example\Main.java:13: error: method of in interface Consumers cannot be applied to given types;
> Consumers.of(Main::exec);
> ^
> required: OutputStreamConsumer
> found: Main::exec
> reason: argument mismatch; invalid method reference
> no suitable method found for exec(Object,OutputStream)
> method Main.exec(Object) is not applicable
> (actual and formal argument lists differ in length)
> method Main.exec(Object,Appendable) is not applicable
> (argument mismatch; OutputStream cannot be converted to Appendable)
> 2 errors
>
> i think this is bug because eclipse jdt compiler can compile the code and
>
> * first exec method has return type and one argument,
> OutputStreamConsumer and WriterConsumer require 2 argument and no return value
> so this is not ambiguous. i think compiler should pick a second exec method.
> * OutputStreamConsumer receives OutputStream, not Appendable.
> so compiler should pick WriterConsumer
>
> my envrionment is below
>
> * javac 1.8.0_20
> * eclipse 4.4.0
>
> thanks
>
> Taichi
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20141008/9caffe71/attachment-0001.html>
More information about the compiler-dev
mailing list