Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eclipse fails where javac and IDEA succeed

Consider the following self-contained sample:

package bloopers;

import java.lang.annotation.Annotation;

public final class Blooper5
{
    interface Converter<T,F>
    {
        T convert( F from );
    }

    interface Identifier<T>
    {
    }

    static class ConvertingIdentifier<F,T> implements Identifier<F>
    {
        ConvertingIdentifier( Converter<T,F> converter )
        {
        }
    }

    static final class AnnotationIdentifier
    {
        Identifier<Annotation> I1 = new ConvertingIdentifier<>( 
            a -> a.annotationType() );
        Identifier<Annotation> I2 = new ConvertingIdentifier<>( 
            Annotation::annotationType ); //<-- ERROR
        Identifier<Annotation> I3 = new ConvertingIdentifier<>( 
            (Converter<Class<? extends Annotation>,Annotation>)
            Annotation::annotationType );
    }
}

The code above compiles just fine under the following:

  • javac from the command line.
  • IntelliJ IDEA configured to use the javac compiler.

But it fails to compile with the following:

  • Eclipse
  • IntelliJ IDEA configured to use the Eclipse compiler.

Eclipse fails to compile the line marked with <-- ERROR, giving the following message:

The constructor Blooper5.ConvertingIdentifier<Annotation,Class<capture#5-of ? extends Annotation>>(Blooper5.Converter<Class<? extends Annotation>,Annotation>) is undefined

Admittedly, this code really pushes the generic parameter type inference capabilities of the compiler, but still, I would like to know precisely what the discrepancy is, no matter how small.

Some exposure of my methods in case someone manages to see something wrong that I fail to see:

The command I used to compile with javac was "c:\Program Files\Java\jdk1.8.0_40\bin\javac" Blooper5.java.

I have version 14.1 of IntelliJ IDEA. Under Project Structure/SDKs I only have "1.8" which points to C:\Program Files\Java\jdk1.8.0_40 and under Project Structure/Modules the specific module is configured to use the "Project SDK (1.8)" which lists as 1.8 (java version "1.8.0_40").

As for Eclipse, I am using Eclipse for RCP and RAP Developers - Version: Luna Release (4.4.0) - Build id: 20140612-0600. Under Preferences/Java/Installed JREs I only have jdk1.8.0_40, and it is the default. Under Execution Environments it is also checked as a "Compatible JRE" of "JavaSE-1.8". And in my Project/Properties/Java Build Path/Libraries the "JRE System Library" is [jdk1.8.0_40].

More noteworthy facts:

  • It is not just me; it also fails on a colleague's (very similar) eclipse installation.

  • IntelliJ IDEA says that the lambda expression a -> a.annotationType() can be replaced with a method reference, but if asked to do so, it does not convert it to Annotation::annotationType; instead, it converts it to (Converter<Class<? extends Annotation>, Annotation>) Annotation:: annotationType.

So, the question:

What is causing these discrepancies between Eclipse and the others, and what can be done to eliminate these discrepancies?

(Obviously, the goal is to eliminate the unfortunately too frequently occurring scenario where one developer commits code which fails to compile on another developer's IDE.)

EDIT: When I originally posted this question I thought that IDEA using the Eclipse compiler also compiled fine, but I was wrong. It turns out that it is possible to get IDEA to fail to compile the above code by selecting the Eclipse compiler. Still, the question is why there is a discrepancy between eclipse and javac.

like image 971
Mike Nakis Avatar asked Mar 30 '15 16:03

Mike Nakis


1 Answers

The answer to "why is there a discrepancy" is straightforward but perhaps not very satisfactory: because compilers have bugs and are furthermore open to interpretation of a very complex language specification. Determining whether it's a bug in javac or Eclipse is a difficult task; I've seen such discrepancies end up being declared both ways, sometimes as Eclipse compiler bugs, sometimes as javac bugs. That determination, especially when it involves generics and new language features (such as lambdas), can get quite tedious and arcane. For example, look at this one that turned out to be a javac bug but did uncover a related issue in Eclipse's compiler: https://bugs.eclipse.org/bugs/show_bug.cgi?id=456459

The best bet is to report it as an Eclipse bug as I did and see if the Eclipse compiler team can/will track it down.

like image 171
E-Riz Avatar answered Nov 03 '22 12:11

E-Riz