change in inference of unchecked calls after JDK-8147493

Maurizio Cimadamore maurizio.cimadamore at
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) {

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 
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:

> 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: <>

More information about the compiler-dev mailing list