Generic constructor thrown type (constructor type variable) is not erased despite of unchecked conversion
Dan Smith
daniel.smith at oracle.com
Fri Sep 4 16:52:35 UTC 2015
This looks like a legitimate javac bug. After some testing, it seems fairly widespread and longstanding -- the return type & throws clause erasure rule is apparently implement incorrectly: javac is performing a substitution before erasure.
I've filed a bug: https://bugs.openjdk.java.net/browse/JDK-8135087
—Dan
> On Aug 28, 2015, at 9:33 AM, Georgiy Rakov <georgiy.rakov at oracle.com> wrote:
>
> Hello,
>
> let's consider following example.
> class MyException extends Exception {}
>
> class MyDerivedException extends MyException {}
>
>
> class MyType<T> {
> MyType(T t) {}
> }
>
> public class Test32 {
> public static void test() {
> try {
> MyDerivedException e1 = new MyDerivedException();
>
> Foo foo = new Foo(e1, new MyType(""));
> } catch (MyDerivedException e2) {
> }
> }
> }
>
> class Foo {
> public <E1 extends MyException> Foo(E1 e, MyType<String> a) throws E1 {
> throw e;
> }
> }
> It compiles successfully on JDK9b78. Now let's consider reasoning presented below. 1. According to following assertion, 15.12.2 is used in order to determine the constructor thrown types:
> ***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.
> 2. According to my understanding the types in throws clause are determined in the last subsection of 15.12.2, that is in 15.12.2.6, which states:
> If the chosen method is generic and the method invocation does not provide explicit type arguments, the invocation type is inferred as specified in §18.5.2.
> 3. 18.5.2 contains following assertion:
> If unchecked conversion was necessary for the method to be applicable during constraint set reduction in §18.5.1, then the parameter types of the invocation type of m are obtained by applying a' to the parameter types of m's type, and the return type and thrown types of the invocation type of m are given by the erasure of the return type and thrown types of m's type. (jls-18.5.2-100-F.1-A)
> and 18.2.2. contains following assertions:
> A constraint formula of the form ‹S → T› is reduced as follows: (jls-18.2.2-100) Otherwise, if T is a parameterized type of the form G<T1, ..., Tn>, and there exists no type of the form G<...> that is a supertype of S, but the raw type G is a supertype of S, then the constraint reduces to true. (jls-18.2.2-100-D) The fourth and fifth cases are implicit uses of unchecked conversion (§5.1.9). These, along with any use of unchecked conversion in the first case, may result in compile-time unchecked warnings, and may influence a method's invocation type (§15.12.2.6). (jls-18.2.2-110)
> 3.1. During reduction constraint [new MyType("") -> MyType<String>] is reduced to [MyType -> MyType<String>]. 3.2. [MyType -> MyType<String>] is reduced to true according to jls-18.2.2-100-D. 3.3. Thus according to jls-18.2.2-110 step 3.2 is considered as applying unchecked conversion. 3.4. Hence according to jls-18.5.2-100-F.1-A the constructor exception type should be erased that is E1 should be erased to MyException which should have caused compilation failure, but compilation succeeds. 3.5. So if I understand correctly javac behaves as if jls-18.5.2-100-F.1-A specified that substitution a' is applied to m's thrown type first, and only after that ctor thrown type is erased. This looks like a spec issue, that is spec should have specified something like: "and the return type and thrown types of the invocation type of m are given by the erasure of the return type and thrown types of m2 where m2 is the result of applying a' to m's type" (I guess the same is true for the return type). Could you please tell if you agree that this is really a spec issue. Thank you, Georgiy.
> <Test32.java>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20150904/32abceba/attachment.html>
More information about the compiler-dev
mailing list