Java 9 ea154 javac compiler error - legit or bug?

Maurizio Cimadamore maurizio.cimadamore at
Thu Feb 9 13:31:04 UTC 2017

Hi Vitaly,
the situation is a tad convoluted; basically there's a long-standing 
javac discrepancy which allowed javac to erase the return type of an 
unchecked call *after* some type inference has been performed. This 
behavior is well described here:

In your example, that means that, since the first actual argument to 
'foo' has type Class<String> and the first formal is Class<T>, javac is 
able to infer that T = String - which gives you a fully instantiated 
'foo' with signature:

String foo(Class<String> c, Collection<? super String> baz)

Then, as an unchecked conversion has been required for this method call 
(for the second argument), javac proceeds to erase the signature - but 
there's nothing to do! That is, erasure(String) = String, so the 
invocation type of the inner most call has a return type 'String'. 
That's different from what the spec says - as the spec wants to erase 
the *declared signature* of the method if an unchecked conversion occurs 
- in which case the invocation return type would be just Object (and a 
compiler error would be issued). This discrepancy will be addressed as 
part of JDK 10.

That said, JDK-8078093 accidentally introduced a change in this area - 
in method context the current javac implementation would erase the 
declared signature; while this behavior is compatible with what the spec 
say, as you observed, it's completely inconsistent with what javac does 
in assignment context, and it's also inconsistent with almost everything 
else javac does (hence the weird error you get 'expected: String - 
found: String'). This is just a plain bug - the fix for 8078093 was 
never meant to alter behavior of type-checking with unchecked calls and 
generic methods.

In the short term we plan to restore the original behavior (as with JDK 
8). In the medium term we plan to get rid of this discrepancy for good.

So, should the program compile? If you follow the spec literally, no, it 
shouldn't. But the aim is to keep stuff like this working, until we come 
up with a more general cleanup in this area.

I hope this clarifies the issue.

Meanwhile, I filed this bug:

to keep track of this issue.


On 09/02/17 04:09, Vitaly Davidovich wrote:
> Hi Maurizio,
> Thanks for the reply.  So you're saying the example using assignment 
> context shouldn't compile either? Also, the call to 'foo' is unchecked 
> in the wildcard argument, but it has a concrete type in the first 
> argument.  Are you saying that any unchecked param results in return 
> type erasure?
> Thanks
> On Wed, Feb 8, 2017 at 8:38 PM Maurizio Cimadamore 
> <maurizio.cimadamore at 
> <mailto:maurizio.cimadamore at>> wrote:
>     Hi,
>     it seems like the behavior you observed started in b83 - as a
>     result of this:
>     I believe the error is correct (although the diagnostic has always
>     been broken since b83 in the 'verbose' mode - the non-verbose mode
>     - w/o -Xdiags:verbose is fine). That is, the call to 'foo' is
>     unchecked, so the return type should be erased. There seems to be
>     an inconsistency in how javac handles this in method context
>     compared to assignment context, and that needs to be looked at.
>     Thanks
>     Maurizio
>     On 08/02/17 19:23, Vitaly Davidovich wrote:
>>     Hi all,
>>     Given the following code:
>>     import java.util.ArrayList;
>>     import java.util.Collection;
>>     public class Foo {
>>         static <T> T foo(Class<T> c, Collection<? super T> baz) {
>>     return null;
>>         }
>>         static void bar(String c) {
>>         }
>>     @SuppressWarnings("unchecked")
>>         public static void main(String[] args) {
>>     // this works
>>     bar(foo(String.class, new ArrayList<String>()));
>>     // this works with a warning
>>     String s = foo(String.class, new ArrayList());
>>     bar(s);
>>     // this causes an error on JDK9
>>     bar(foo(String.class, new ArrayList()));
>>         }
>>     }
>>     javac 9-ea (build 9-ea+154) fails with this interesting error (on
>>     the last line in main, as the comments there indicate):
>> error: method bar in class Foo cannot be applied to
>>     given types;
>>     bar(foo(String.class, new ArrayList()));
>>                     ^
>>       required: String
>>       found: String
>>       reason: argument mismatch; Object cannot be converted to String
>>     1 error
>>     Java 8 compiles fine, and the other 2 lines compile in the same
>>     java 9 build as well.
>>     Is this a javac bug or legit? It seems like a compiler error.  At
>>     a minimum, the diagnostic output "required String, found String"
>>     is confusing.
>>     Thanks
> -- 
> Sent from my phone

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the compiler-dev mailing list