The type of instance creation expression with types arguments provided is not affected by 15.12.2.6?

Dan Smith daniel.smith at oracle.com
Thu Sep 3 19:24:13 UTC 2015


> On Aug 12, 2015, at 7:59 AM, Georgiy Rakov <georgiy.rakov at oracle.com> wrote:
> 
> Hello,
> 
> following new spec presented in JDK-8073593 states:
> Otherwise, the class instance creation expression does not use <> to elide class ***or interface*** type arguments. 
> 
> ***If C is not an anonymous class,*** let T be the type denoted by C followed by any class type arguments in the expression. The process specified in §15.12.2, modified to handle constructors, is used to select one of the constructors of T and determine its throws clause. 
> ...
> 
> Otherwise, the return type is T. 
> ...
> 
> The type of the class instance creation expression is the return type of the chosen constructor, as defined above.
> In particular it says that 15.12.2 is applied in order to determine the throws clause. If I understand correctly it means that the throws types can be changed by 15.12.2.6 if unchecked conversion was necessary for the chosen method (ctor) to be applicable. But 15.12.2.6 also changes the return type in the same case; yet the assertion presented above doesn't mention that the return type is determined by the process specified in 15.12.2 (only throws clause is mentioned). So could you please tell if I understand correctly that it means that the return type of instance creation expression is not changed as per 15.12.2.6 in this case. I'm asking about this because I've come across the fact that following code compiles successfully on JDK9b76:
> class MyType<T> {}
> 
> class List<T> {
>     List<T> copyThis() { return null; }
> }
> 
> public class Test28 {
>     static <T> void m2(List<T> list1, List<T> list2) {}
>     static <U> List<U> m1(U item) {
>         return null;
>     }
>     static void test() {
>         m2(new List<Foo<String>>(), m1(new Foo<String>(new MyType()).copyThis()).copyThis());
>     }
> }
> 
> class Foo<T> {
>     <U> Foo(MyType<U> a2){}
>     Foo<T> copyThis() {
>         return null;
>     }
> }
> 
> 
> 
> In this code unchecked conversion is necessary in order for the Foo constructor to be applicable, so if 15.12.2.6 were to change the return type of constructor it would be raw type Foo, which finally would cause compilation failure due to the incompatible equality constraints on T inferred. So could you please also confirm that this is not a bug and javac behaves according to spec for the reasons presented above.

FWIW, note that you're looking at established spec text from JLS 7, and JDK-8073593 has nothing to do with the issue.  JLS 3 had the same problem, though the text was different.

The mapping between constructors and overload resolution is not as clear as it should be.  This is a known issue: see JDK-8034925.  (Glad you noticed it too, though!)  For now, it's fair to assume that javac, as the reference implementation, establishes the intended behavior, and that the spec should be updated to reflect that.

—Dan



More information about the compiler-dev mailing list