Consider the following code Java code:
import java.util.function.Supplier;
interface Main {
interface X<T> {
X<T> self();
}
static X<?> makeX() {return null;}
static <R> X<R> create(Supplier<? extends R> supplier) {return null;}
static X<X<?>> methodRef() {
return create(Main::makeX).self();
}
static X<X<?>> lambda() {
return create(() -> makeX()).self();
}
}
The method `methodRef` can be compiled without problems, while the method `lambda` is rejected with the following error message:
Main.java:17: error: incompatible types: X<X<CAP#1>> cannot be converted to X<X<?>>
return create(() -> makeX()).self();
^
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
1 error
error: compilation failed
According to the specification, the call in methodRef() method should be similarly rejected, as the capture conversion should be applied to the return type (JLS 15.13.2):
A method reference expression is congruent with a function type if both of the following are true:
- The function type identifies a single compile-time declaration corresponding to the reference.
- One of the following is true:
- The result of the function type is void.
- The result of the function type is R, and the result of **applying capture conversion** (§5.1.10) to the return type of the invocation type (§15.12.2.6) of the chosen compile-time declaration is R' (where R is the target type that may be used to infer R'), and neither R nor R' is void, and R' is compatible with R in an assignment context.
Currently, it looks like the type of create(Main::makeX) is X<X<?>>, while it should be X<X<CAP#1>>. The type of create(() -> makeX()) is X<X<CAP#1>>, which is correct.
import java.util.function.Supplier;
interface Main {
interface X<T> {
X<T> self();
}
static X<?> makeX() {return null;}
static <R> X<R> create(Supplier<? extends R> supplier) {return null;}
static X<X<?>> methodRef() {
return create(Main::makeX).self();
}
static X<X<?>> lambda() {
return create(() -> makeX()).self();
}
}
The method `methodRef` can be compiled without problems, while the method `lambda` is rejected with the following error message:
Main.java:17: error: incompatible types: X<X<CAP#1>> cannot be converted to X<X<?>>
return create(() -> makeX()).self();
^
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
1 error
error: compilation failed
According to the specification, the call in methodRef() method should be similarly rejected, as the capture conversion should be applied to the return type (JLS 15.13.2):
A method reference expression is congruent with a function type if both of the following are true:
- The function type identifies a single compile-time declaration corresponding to the reference.
- One of the following is true:
- The result of the function type is void.
- The result of the function type is R, and the result of **applying capture conversion** (§5.1.10) to the return type of the invocation type (§15.12.2.6) of the chosen compile-time declaration is R' (where R is the target type that may be used to infer R'), and neither R nor R' is void, and R' is compatible with R in an assignment context.
Currently, it looks like the type of create(Main::makeX) is X<X<?>>, while it should be X<X<CAP#1>>. The type of create(() -> makeX()) is X<X<CAP#1>>, which is correct.
- duplicates
-
JDK-8369517 Compilation mismatch for equivalent lambda and method reference
-
- In Progress
-