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