Java 9 ea154 javac compiler error - legit or bug?

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Feb 23 22:16:20 UTC 2017


Phew - thanks!

Maurizio


On 23/02/17 22:05, Vitaly Davidovich wrote:
> Hi Maurizio,
>
> Just wanted to follow up and confirm that 157 fixes the issue - thanks 
> again for the lightning turnaround!
>
> On Thu, Feb 9, 2017 at 5:04 PM Vitaly Davidovich <vitalyd at gmail.com 
> <mailto:vitalyd at gmail.com>> wrote:
>
>     Awesome - thanks!
>
>     On Thu, Feb 9, 2017 at 5:03 PM Maurizio Cimadamore
>     <maurizio.cimadamore at oracle.com
>     <mailto:maurizio.cimadamore at oracle.com>> wrote:
>
>
>         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
>
>     -- 
>     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/20170223/cbdf0876/attachment-0001.html>


More information about the compiler-dev mailing list