Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Cyclic generic type relation doesn't allow cast from supertype (javac bug)

I encounter a totally strange behavior of the Java compiler.
I can't cast a supertype to a subtype when cyclic generic type relation is involved.

JUnit test case to reproduce the problem:

public class _SupertypeGenericTest {

    interface ISpace<S extends ISpace<S, A>, A extends IAtom<S, A>> {
    }

    interface IAtom<S extends ISpace<S, A>, A extends IAtom<S, A>> {
    }

    static class Space
            implements ISpace<Space, Atom> {
    }

    static class Atom
            implements IAtom<Space, Atom> {
    }

    public void test() {
        ISpace<?, ?> spaceSupertype = new Space();
        IAtom<?, ?> atomSupertype = new Atom();

        Space space = (Space) spaceSupertype;  // cast error
        Atom atom = (Atom) atomSupertype;  // cast error
    }
}

Compiler error output:

_SupertypeGenericTest.java:33: inconvertible types
found   : pinetag.data._SupertypeGenericTest.ISpace<capture#341 of ?,capture#820 of ?>
required: pinetag.data._SupertypeGenericTest.Space
                Space space = (Space) spaceSupertype;
                                    ^

_SupertypeGenericTest.java:34: inconvertible types
found   : pinetag.data._SupertypeGenericTest.IAtom<capture#94 of ?,capture#48 of ?>
required: pinetag.data._SupertypeGenericTest.Atom
                Atom atom = (Atom) atomSupertype;
                                ^
2 errors

Note: I'm using Netbeans latest trunk, bundled Ant, latest Java 6 release.
I tried using Ant from command line (Netbeans generates a build.xml file) but it results in same errors.

What is wrong?
Is there an elegant way solve the problem?

The strange thing is: Netbeans doesn't mark errors (not even warnings) in given code.

EDIT:
No, now I understand nothing!
Eclipse 3.4.1 doesn't mark neither warnings nor errors, and compiles the code without trouble!!!
How can this be? I thought, using Ant from command line along with build.xml provided by Netbeans' would be neutral.
Am I missing something?

EDIT 2:
Using JDK7 library and JDK7 code format, netbeans compiles without errors/warnings!
(I'm using 1.7.0-ea-b55)

EDIT 3:
Changed title to indicate that we're dealing with a javac bug.

like image 933
ivan_ivanovich_ivanoff Avatar asked Nov 05 '22 21:11

ivan_ivanovich_ivanoff


1 Answers

I don't claim to easily understand those complex generic types, but if you find some code that compiles in javac and doesn't in ecj (the eclipse compiler), then file a bug report with both Sun and Eclipse and describe the situations cleary (best if you also mention that you filed both bug reports and mention their respective URLs, although for Sun it may take a while before the bug is publicly accessible).

I've done that in the past and got really good responses where

  1. one of the teams figured out what the correct approach was (give compile error, warning or nothing)
  2. and the faulty compiler was fixed

Since both compilers implement the same spec, one of them is by definition wrong, if only one of them compiles the code.

For the record:

I tried to compile the sample code with javac (javac 1.6.0_13) and ecj (Eclipse Java Compiler 0.894_R34x, 3.4.2 release) and javac complained loudly and failed to produce any .class files, while ecj only complained about some unused variables (warnings) and produced all the expected .class files.

like image 92
Joachim Sauer Avatar answered Nov 12 '22 17:11

Joachim Sauer