A DESCRIPTION OF THE PROBLEM :
The provided code snippet does not compile, even though it should.
I think the compiler cannot correctly resolve the generic type hint in the method reference when used as a parameter of another generic method.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run provided code sample.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The provided test case compiles without errors.
ACTUAL -
java: incompatible types: cannot infer type-variable(s) T
(argument mismatch; invalid method reference
incompatible types: java.lang.Object cannot be converted to S)
---------- BEGIN SOURCE ----------
import java.util.function.BiFunction;
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
Example example = new Example();
assert example.methodThatDoesNotCompile("should getpostfix").equals("should getpostfix postfix");
}
private static class Example {
private <S> String methodThatDoesNotCompile(S exampleArgument) {
return exampleMethodThatAcceptsReference(this::<S>exampleMethodUsedAsReference).apply(exampleArgument);
}
private <T> Function<T, String> exampleMethodThatAcceptsReference(BiFunction<T, String, String> referenceAsArgument) {
return i -> referenceAsArgument.apply(i, " postfix");
}
private <U> String exampleMethodUsedAsReference(U first, String second) {
return first.toString() + second;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Changing methodThatDoesNotCompile to one of these options:
Making the type explicit without generic type in reference (should always be possible, but cumbersome).
private <S> String methodThatDoesNotCompile(S exampleArgument) {
BiFunction<S, String, String> exampleMethodUsedAsReference = this::exampleMethodUsedAsReference;
return exampleMethodThatAcceptsReference(exampleMethodUsedAsReference).apply(exampleArgument);
}
or putting the generic type in the outer generic method:
private <S> String methodThatDoesNotCompile(S exampleArgument) {
return this.<S>exampleMethodThatAcceptsReference(this::exampleMethodUsedAsReference).apply(exampleArgument);
}
or leaving out the generic type hint (only possible in certain cases like this reproducable test case, but not necessarily always easy):
private <S> String methodThatDoesNotCompile(S exampleArgument) {
return exampleMethodThatAcceptsReference(this::exampleMethodUsedAsReference).apply(exampleArgument);
}
The provided code snippet does not compile, even though it should.
I think the compiler cannot correctly resolve the generic type hint in the method reference when used as a parameter of another generic method.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run provided code sample.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The provided test case compiles without errors.
ACTUAL -
java: incompatible types: cannot infer type-variable(s) T
(argument mismatch; invalid method reference
incompatible types: java.lang.Object cannot be converted to S)
---------- BEGIN SOURCE ----------
import java.util.function.BiFunction;
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
Example example = new Example();
assert example.methodThatDoesNotCompile("should getpostfix").equals("should getpostfix postfix");
}
private static class Example {
private <S> String methodThatDoesNotCompile(S exampleArgument) {
return exampleMethodThatAcceptsReference(this::<S>exampleMethodUsedAsReference).apply(exampleArgument);
}
private <T> Function<T, String> exampleMethodThatAcceptsReference(BiFunction<T, String, String> referenceAsArgument) {
return i -> referenceAsArgument.apply(i, " postfix");
}
private <U> String exampleMethodUsedAsReference(U first, String second) {
return first.toString() + second;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Changing methodThatDoesNotCompile to one of these options:
Making the type explicit without generic type in reference (should always be possible, but cumbersome).
private <S> String methodThatDoesNotCompile(S exampleArgument) {
BiFunction<S, String, String> exampleMethodUsedAsReference = this::exampleMethodUsedAsReference;
return exampleMethodThatAcceptsReference(exampleMethodUsedAsReference).apply(exampleArgument);
}
or putting the generic type in the outer generic method:
private <S> String methodThatDoesNotCompile(S exampleArgument) {
return this.<S>exampleMethodThatAcceptsReference(this::exampleMethodUsedAsReference).apply(exampleArgument);
}
or leaving out the generic type hint (only possible in certain cases like this reproducable test case, but not necessarily always easy):
private <S> String methodThatDoesNotCompile(S exampleArgument) {
return exampleMethodThatAcceptsReference(this::exampleMethodUsedAsReference).apply(exampleArgument);
}