| Summary: | Failure in overload resolution using functional interface with wildcard | ||
|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Jens Auer <jens.auer> |
| Component: | Core | Assignee: | JDT-Core-Inbox <jdt-core-inbox> |
| Status: | CLOSED WONTFIX | QA Contact: | Stephan Herrmann <stephan.herrmann> |
| Severity: | normal | ||
| Priority: | P3 | CC: | jens.auer, stephan.herrmann |
| Version: | 4.7 | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Windows 7 | ||
| Whiteboard: | stalebug | ||
I could narrow the problem down to something related to type-inference with widlcards. The following code compiles on javac, but not with ecj:
static final class A {}
public static <T> String g(ToIntFunction<? extends A f) {
return null;
}
public static <T> String g(ToDoubleFunction<? extends A> f) {
return null;
}
private static int double2int(A x) {
return 2;
}
public static void main(String[] args) {
g(HelloWorld::double2int);
}
Removing the wildcard arguments also removes the error:
public static <T> String g(ToIntFunction<A> f) {
return null;
}
public static <T> String g(ToDoubleFunction<A> f) {
return null;
}
private static int double2int(Ax) {
return 2;
}
public static void main(String[] args) {
g(RadarSimulation::double2int);
}
I am not sure what to make of this.
I looked the rules of method reference type inference, and from my understanding, the method reference is assignable to both ToIntFunction<T> and To DoubleFunction<T> because the return type int is assignment compatible to double. So the method reference is congruent with both types and thus compatible in an invocation context. May be a javac bug? I've also asked on Stackoverflow to clarify if this is a Java or ECJ issue: https://stackoverflow.com/questions/45878208/overload-resolution-with-method-references-and-function-interface-specialization Thanks for your investigations. I'll wait if s.o. on SO makes an argument for javac's behavior in this case. Hi Stephan, there was an answer on SO which IMHO confirms the behavior of javac: https://stackoverflow.com/questions/45878208/overload-resolution-with-method-references-and-function-interface-specialization/45891522#45891522 The question is if ToIntFunction is more specific than ToDoubleFunction for the method reference Test::double2int during overload resolution. It turns that I forgot to take the transitivity of the supertype relation into account when looking at the return type: double >₁ float float >₁ long long >₁ int The supertype relation being a reflexive and transitive closure of the direct supertype relation means that from (double >₁ float) ∧ (float >₁ long) ∧ (long >₁ int) follows double :> int. From this, it can be concluded that double >1 int and thus in 15.12.2.5's case for method references, ToIntFunction is more specific than ToDoubleFunction. I also want to point out that for the same code without wildcard arguments ecj does not find any ambiguities.
public static <T> String g(ToIntFunction<A> f) {
return null;
}
public static <T> String g(ToDoubleFunction<A> f) {
return null;
}
private static int double2int(Ax) {
return 2;
}
public static void main(String[] args) {
g(RadarSimulation::double2int);
}
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. As such, we're closing this bug. If you have further information on the current state of the bug, please add it and reopen this bug. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant. -- The automated Eclipse Genie. |
Eclipse 4.7 with JDT 3.13.0.v20170612-0950 reports in error in the call map(oEmpty, Test::double2int): import java.util.function.ToDoubleFunction; import java.util.function.ToIntFunction; public class Test { static class Generic<T> { } public static <T> String map(Generic<T> o, ToIntFunction<? super T> f) { return null; } public static <T> Number map(Generic<T> o, ToDoubleFunction<? super T> f) { return null; } private static int double2int(double x) { return 2; } public static void main(String[] args) { Generic<Double> oEmpty = new Generic<>(); map(oEmpty, Test::double2int); } } Description Resource Path Location Type The method map(Test.Generic<Double>, ToIntFunction<? super Double>) is ambiguous for the type Test Test.java /Playground/src/sandbox line 25 Java Problem Javac from jdk8 and pre-release jdk9 both accept the code. I am not very familiar with the details of overload resolution of the Java language. double2int is assignable to both ToIntFunction and ToDoubleFunction, so intuitively I can see why it could be ambiguous. However, the assignment to ToDoubleFunction involves a conversion from the int result to double, so I would expect that ToIntFunction is a better match and the ambiguity is resolved.