-
Bug
-
Resolution: Fixed
-
P4
-
8
Type inference's handling of method references may allow an out-of-scope type variable to be inferred as a method type argument. This outcome should be prohibited, since the problematic type variable is meaningless at the call site.
Example:
interface F<T> {
<X> Map<T,X> newMap();
}
<K> Map<K,K> emptyMap();
<Z> void test(F<Z> arg);
test(this::emptyMap); // specified: okay; should be: error; javac: error
Type inference will proceed as follows:
this::emptyMap --> F<z> // 18.5.2
Map<k,k> --> Map<z,X> // 18.2.1
{ k=z, k=X } // 18.2.3
{ z=X, k=X }
The type variable 'X' is not in scope at the call site.
The solution is probably to prohibit such outcomes in 18.5.2 or 18.2.1, producing 'false' instead. This is not completeness-preserving, but is probably acceptable.
Note that this is an extremely narrow use case. Requirements include:
- A generic functional interface, F, with a generic method, m1
- Return type of m1 includes a type parameter of F and a type parameter of m1 that doesn't appear in m1's parameter types
- A generic method, m2, with a parameter type that is a parameterization of F mentioning one of m2's type parameters
- A method reference to a generic method, m3, as an argument to m2, where m3 has a type parameter in its return type
After all of these, we end up with a constraint similar to 'Map<k,k> --> Map<z,X>', and it is further necessary that the resulting bounds lead to a resolution in which m2's inference variable (z) is instantiated with a type that mentions m1's type parameter (X). (It's arguably acceptable for m3's inference variable (k) to be instantiated with a type that mentions m1's type parameter (X), because the "invocation" occurs in a place where X is in scope.)
Example:
interface F<T> {
<X> Map<T,X> newMap();
}
<K> Map<K,K> emptyMap();
<Z> void test(F<Z> arg);
test(this::emptyMap); // specified: okay; should be: error; javac: error
Type inference will proceed as follows:
this::emptyMap --> F<z> // 18.5.2
Map<k,k> --> Map<z,X> // 18.2.1
{ k=z, k=X } // 18.2.3
{ z=X, k=X }
The type variable 'X' is not in scope at the call site.
The solution is probably to prohibit such outcomes in 18.5.2 or 18.2.1, producing 'false' instead. This is not completeness-preserving, but is probably acceptable.
Note that this is an extremely narrow use case. Requirements include:
- A generic functional interface, F, with a generic method, m1
- Return type of m1 includes a type parameter of F and a type parameter of m1 that doesn't appear in m1's parameter types
- A generic method, m2, with a parameter type that is a parameterization of F mentioning one of m2's type parameters
- A method reference to a generic method, m3, as an argument to m2, where m3 has a type parameter in its return type
After all of these, we end up with a constraint similar to 'Map<k,k> --> Map<z,X>', and it is further necessary that the resulting bounds lead to a resolution in which m2's inference variable (z) is instantiated with a type that mentions m1's type parameter (X). (It's arguably acceptable for m3's inference variable (k) to be instantiated with a type that mentions m1's type parameter (X), because the "invocation" occurs in a place where X is in scope.)
- relates to
-
JDK-8042285 15.12.2.5: Describe treatment of generic function types
-
- Closed
-
-
JDK-8016203 18.2.1: Derive inference constraints from non-overloaded generic method references
-
- Open
-