JDK-6894753 : Diamond operator and anonymous class
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Cannot Reproduce
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2009-10-23
  • Updated: 2012-03-22
  • Resolved: 2010-07-28
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7Resolved
Related Reports
Relates :  
Relates :  
Description
The following code crashes javac b73:

class U {}
interface I {}
class Child extends U implements I {}

interface Foo<T extends U & I> {
    Foo testMethod() ;
}

public class expr74601m2  {
    public static void main(String argv[]) {
     Foo<Child> t1 = new Foo<>() {
            public Foo testMethod() { return null; }
        }.testMethod();
    }
}

Here is the output:

An exception has occurred in the compiler (1.7.0-ea). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport)  after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report.  Thank you.
java.lang.AssertionError
        at com.sun.tools.javac.jvm.ClassWriter.enterInner(ClassWriter.java:1014)
        at com.sun.tools.javac.jvm.ClassWriter.assembleClassSig(ClassWriter.java:369)
        at com.sun.tools.javac.jvm.ClassWriter.assembleSig(ClassWriter.java:297)
        at com.sun.tools.javac.jvm.ClassWriter.assembleSig(ClassWriter.java:396)
        at com.sun.tools.javac.jvm.ClassWriter.assembleClassSig(ClassWriter.java:388)
        at com.sun.tools.javac.jvm.ClassWriter.assembleSig(ClassWriter.java:297)
        at com.sun.tools.javac.jvm.ClassWriter.writeClassFile(ClassWriter.java:1675)
        at com.sun.tools.javac.jvm.ClassWriter.writeClass(ClassWriter.java:1597)
        at com.sun.tools.javac.main.JavaCompiler.genCode(JavaCompiler.java:696)
        at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1393)
        at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1361)
        at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:851)
        at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:810)
        at com.sun.tools.javac.main.Main.compile(Main.java:400)
        at com.sun.tools.javac.main.Main.compile(Main.java:318)
        at com.sun.tools.javac.main.Main.compile(Main.java:309)
        at com.sun.tools.javac.Main.compile(Main.java:82)
        at com.sun.tools.javac.Main.main(Main.java:67)

Everything compiles fine when I do one of the following:
- remove .testMethod() 
- remove extends U & I 
- use <Child> instead of <>.
 
This test will be integrated into jck soon (probably b26).
-
-
examples 2 and 3 are incorrect, please ignore.

Comments
EVALUATION This has been fixed as part of 6939620 - now the compiler reject the code with an error.
28-07-2010

EVALUATION 1) I guess javac infers U&I as the type argument for the diamond. 2) Things would be clearer if Foo<T>.testMethod returned Foo<T> rather than Foo. (The body of the anonymous class can be empty.) Then, Foo<> would be inferred as Foo<U&I>, and the testMethod invocation will return a Foo<U&I> to compare against Foo<Child> on the LHS ... and that should fail. Having testMethod return Foo causes an unchecked warning at the assignment, which is needless complexity. 3) While this test is excellent for demonstrating the anonymous class+intersection type problem, a good related test would be to drop testMethod and just have 'new Foo<>()' on the RHS. Ideally, diamond would be inferred as Foo<Child>. However, the lack of subtype rules for intersection types makes that Very Hard. The following code shows that extending U and implementing I is not enough to make Child a subtype of U&I: class U {} interface I {} class Child extends U implements I {} <T extends U & I> void foo(T x) { return null; } foo(new Child()); // Does not compile
04-12-2009

EVALUATION This problem is due to a subtle interaction between the attribution code for anonymous inner classes and the diamond type-inference scheme. The declaration corresponding to an anonymous inner class gets attributed on the fly - if the diamond operator has been used, it is necessary to change the supertype/superinterface of the class declaration corresponding to the anon class. In all failing cases we have that the parameter type for such instantiated type contains an intersection type. Since there's no AST representation for intersection types, javac fails to create an AST node for the inferred type, and this result in the crashes described in this report. There are two ways for fixing this problem. One is to add AST internal support for intersection types - so that we can keep javac happy. Another is to change the attribution scheme for inner classes (but I don't see this as a feasible approach).
23-10-2009