Java 9 ea154 javac compiler error - legit or bug?
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Thu Feb 9 22:03:13 UTC 2017
On 09/02/17 16:39, Vitaly Davidovich wrote:
> Hi Maurizio,
>
> Thanks for the elaboration - much appreciated.
>
> Which EA build do you think will have a fix for this issue?
I've just pushed this today, so - finger crossed - it should make the
next one (157)
Maurizio
>
> On Thu, Feb 9, 2017 at 8:31 AM Maurizio Cimadamore
> <maurizio.cimadamore at oracle.com
> <mailto:maurizio.cimadamore at oracle.com>> wrote:
>
> 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:
>
> https://bugs.openjdk.java.net/browse/JDK-8135087
>
> 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:
>
> https://bugs.openjdk.java.net/browse/JDK-8174249
>
> to keep track of this issue.
>
> Maurizio
>
>
>
> 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 oracle.com
>> <mailto:maurizio.cimadamore at oracle.com>> wrote:
>>
>> Hi,
>> it seems like the behavior you observed started in b83 - as a
>> result of this:
>>
>> https://bugs.openjdk.java.net/browse/JDK-8078093
>>
>> 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):
>>>
>>> Foo.java:23: 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
>
> --
> Sent from my phone
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20170209/274f1b02/attachment-0001.html>
More information about the compiler-dev
mailing list