The return type of instance creation expression with diamond and class body should be anonymous class type

Georgiy Rakov georgiy.rakov at oracle.com
Thu Aug 6 16:07:43 UTC 2015


Hello,

let's consider following example:

class List<T> {
List() {}
List<T> getThis() {
return new List();
}
}

class Foo<T> {
public Foo(T a1){}
}

public class Test25 {
public static <T> List<T> m1(T item) {
List l = new List();
return l;
}
public static <U> void m2(List<U> list1, List<U> list2) { }
public static void test() {
m2(new List<Foo<String>>(), m1(new Foo<>("str"){ }).getThis());
}
}

This example compiles successfully on JDK9b75. But according to my 
understanding the compilation should have failed. The reasons for this 
are presented below:

1. JDK-8073593 
<https://bugs.openjdk.java.net/browse/JDK-8073593?focusedCommentId=13622110&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13622110> 
specifies following assertion:

    ***If C is an anonymous class, then the chosen constructor is the
    constructor of the anonymous class. The return type is the anonymous
    class type.***

current JLS 9 15.9.1 spec defines following assertion:

    The type of the class instance creation expression is the return
    type of the chosen constructor, as defined above.

so together these assertions lead to the fact that the type of instance 
creation expression "new Foo<>("str"){ } " is anonymous class type, 
let's denote it as "anonymous Foo<String>".

2. Thus when m1 is invoked, that is "m1(new Foo<>("str"){ })", the 
invocation return type is List<anonymous Foo<String>>.

3. Hence when getThis is invoked, that is "m1(new Foo<>("str"){ 
}).getThis()", the invocation return type is List<anonymous Foo<String>> 
as well.

4. Finally when m2 method is invoked type inference cause two equality 
constraints to be created that is: U = Foo<String> and U = (anonymous 
Foo<String>), together they should lead to compilation failure, but 
compilation succeeds.

This seems to be a javac bug. Could you please confirm if it really is.

Please note, that if diamond is replaced with String type argument, that 
is "new Foo<String>("str"){ }" the compilation fails as expected:

    Error:(19, 9) java: method m2 in class Test25 cannot be applied to
    given types;
       required: List<U>,List<U>
       found: List<Foo<java.lang.String>>,List<<anonymous
    Foo<java.lang.String>>>
       reason: inference variable U has incompatible equality
    constraints <anonymous Foo<java.lang.String>>,Foo<java.lang.String>

Thank you,
Georgiy.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20150806/6ed3c9d5/attachment.html>
-------------- next part --------------
class List<T> {
    List() {}
    List<T> getThis() {
        return new List();
    }
}

class Foo<T> {
    public Foo(T a1){}
}

public class Test25  {
    public static <T> List<T> m1(T item) {
        List l = new List();
        return l;
    }
    public static <U> void m2(List<U> list1, List<U> list2) { }
    public static void test() {
        m2(new List<Foo<String>>(),  m1(new Foo<>("str"){ }).getThis());
    }
}


More information about the compiler-dev mailing list