change in inference of unchecked calls after JDK-8147493
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Tue Jan 26 12:36:10 UTC 2016
On 26/01/16 10:18, Maurizio Cimadamore wrote:
> I will look into this. Thanks.
Update: I believe this problem has been there for a long time, but the
fact that unchecked conversion were not propagated correctly allowed
this program to compile (in fact, if you check with an earlier JDK 8
build, there are some spurious unchecked warnings generated as a result).
I believe the program should be accepted - I've alpha-renamed
type-variables in your example to make matters a bit clearer:
abstract class Test {
interface R<Z> {}
interface Q<Y> {}
interface T { <N> Q<N> n(R<N> r); }
abstract <I> I isA(Class<I> t);
abstract <W> S<W> w(W t);
interface S<X> { S<X> t(X value); }
void f(T t, Q<String> q) {
w(t.n(isA(R.class))).t(q);
}
}
The big issue occurs when we call 't.n' - performing applicability
inference of its argument means evaluating the expression constraint
isA() -> R<N>, and such a constraint should be evaluated by performing
invocation type inference (18.5.2).
According to 18.5.2, given that isA() returns a bare inference variable
('I') and given that this inference variable has an equality constraints
(R) and given that there's no paramaterization of the target type R<N>
such that R <: R<N>, eager instantiation of 'I' should occur.
Then, following 18.5.2 we should set up a type compatibility constraints
of the kind R -> R<N>, and that kind of compatibility constraint clearly
generates an unchecked warning (as per 18.2.2). So, popping back, we
have found an unchecked warning while proving applicability of 't.n'.
This should mean that invocation type-inference for 't.n' we should
effectively erase the return type:
"If unchecked conversion was necessary for the method to be applicable
during constraint set reduction in §18.5.1
<https://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html#jls-18.5.1>,
the constraint formula ‹|R| → T› is reduced and incorporated with B_2 ."
Which should mean W = |Q|, and then W<Q>'s member 't' should have a type
(Q)S<Q>, which should be compatible with Q<String>.
In terms of the implementation, javac loses the unchecked warning that
is generated when evaluating isA() -> R<N>; this means that the method
call is not treated as unchecked.
I've filed: https://bugs.openjdk.java.net/browse/JDK-8148213
Maurizio
>
> Maurizio
>
> On 26/01/16 04:03, Liam Miller-Cushon wrote:
>> The fix for JDK-8147493 (regression when type-checking unchecked
>> method calls) prevents the following code from compiling. It is
>> accepted by 8, and earlier versions of 9-dev. The return type of
>> w(...) is now being inferred as S<Q<Object>>. Shouldn't the unchecked
>> call cause return types to be erased?
>>
>> abstract class Test {
>>
>> interface R<E> {}
>> interface Q<T> {}
>> interface T { <E> Q<E> n(R<E> r); }
>> abstract <T> T isA(Class<T> t);
>> abstract <T> S<T> w(T t);
>> interface S<T> { S<T> t(T value); }
>>
>> void f(T t, Q<String> q) {
>> w(t.n(isA(R.class))).t(q);
>> }
>> }
>>
>>
>> error: incompatible types: Q<String> cannot be converted to Q<Object>
>> w(t.n(isA(R.class))).t(q);
>> ^
>>
>> Thanks,
>> Liam
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20160126/0d452198/attachment-0001.html>
More information about the compiler-dev
mailing list