Java 9 ea154 javac compiler error - legit or bug?

Vitaly Davidovich vitalyd at gmail.com
Thu Feb 9 22:04:47 UTC 2017


Awesome - thanks!

On Thu, Feb 9, 2017 at 5:03 PM Maurizio Cimadamore <
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> 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> 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20170209/1d1edd69/attachment.html>


More information about the compiler-dev mailing list