test/tools/javac/types/GenericTypeWellFormednessTest.java

Wed, 06 Apr 2011 20:33:44 -0700

author
ohair
date
Wed, 06 Apr 2011 20:33:44 -0700
changeset 962
0ff2bbd38f10
parent 821
c8d312dd17bc
child 2525
2eb010b6cb22
permissions
-rw-r--r--

7033660: Update copyright year to 2011 on any files changed in 2011
Reviewed-by: dholmes

     1 /*
     2  * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  */
    24 /*
    25  * @test
    26  * @bug 7007432 7006109
    27  * @summary Test generic types well-formedness
    28  * @author mcimadamore
    29  * @library .
    30  * @run main GenericTypeWellFormednessTest
    31  */
    33 import com.sun.tools.javac.code.BoundKind;
    34 import com.sun.tools.javac.code.Type;
    35 import com.sun.tools.javac.code.Type.*;
    36 import com.sun.tools.javac.code.Symbol;
    37 import com.sun.tools.javac.code.Symbol.*;
    38 import java.lang.reflect.Array;
    40 /**
    41  * Check parameterized type well-formedness. This test executes a number of checks
    42  * in order to establish as to whether an instantiation of a generic type conforms
    43  * to the generic class' declared bounds.
    44  */
    45 public class GenericTypeWellFormednessTest extends TypeHarness {
    47     static int executedCount = 0;
    48     static int ignoredCount = 0;
    50     InstantiableType[] rows;
    51     Type[] columns;
    53     static class InstantiableType {
    54         protected Type type;
    56         public InstantiableType(Type type) {
    57             this.type = type;
    58         }
    60         Type inst(Type clazz) {
    61             return type;
    62         }
    63     }
    65     enum Result {
    66         /* generic type is well-formed w.r.t. declared bounds */
    67         OK(true),
    68         /* generic type is not well-formed w.r.t. declared bounds */
    69         FAIL(false),
    70         /* generic type is not well-formed w.r.t. declared bounds according to the JLS 3rd,
    71          * but javac allows it (spec for generic type well-formedness is overly restrictive)
    72          * See regression test test/tools/generics/wildcards/T5097548.java
    73          */
    74         IGNORE(false);
    76         boolean value;
    78         Result(boolean value) {
    79             this.value = value;
    80         }
    81     }
    83     static final Result T = Result.OK;
    84     static final Result F = Result.FAIL;
    85     static final Result I = Result.IGNORE;
    87     /*is a type in 'rows' a valid instantiation for the generic class in 'col' ? */
    88     Result[][] isValidInstantiation = {
    89                      //Foo<X>, Foo<X ext Object>, Foo<X ext Number>, Foo<X ext Foo<X>>, Foo<X ext Foo<+X>>, Foo<X ext Foo<-X>>, Foo<X ext Foo<?>>
    90     /*Foo<Object>*/  { T     , T                , F                , F                , F                 , F                 , F },
    91     /*Foo<Number>*/  { T     , T                , T                , F                , F                 , F                 , F },
    92     /*Foo<Integer>*/ { T     , T                , T                , F                , F                 , F                 , F },
    93     /*Foo<Double>*/  { T     , T                , T                , F                , F                 , F                 , F },
    94     /*Foo<String>*/  { T     , T                , F                , F                , F                 , F                 , F },
    95     /*Foo<X1>*/      { T     , T                , F                , F                , F                 , F                 , F },
    96     /*Foo<X2>*/      { T     , T                , T                , F                , F                 , F                 , F },
    97     /*Foo<X3>*/      { T     , T                , T                , F                , F                 , F                 , F },
    98     /*Foo<X4>*/      { T     , T                , T                , F                , F                 , F                 , F },
    99     /*Foo<X5>*/      { T     , T                , F                , F                , F                 , F                 , F },
   100     /*Foo<X6>*/      { T     , T                , F                , T                , T                 , T                 , T },
   101     /*Foo<+Object>*/ { T     , T                , I                , I                , I                 , I                 , I },
   102     /*Foo<+Number>*/ { T     , T                , T                , F                , F                 , F                 , F },
   103     /*Foo<+Integer>*/{ T     , T                , T                , F                , F                 , F                 , F },
   104     /*Foo<+Double>*/ { T     , T                , T                , F                , F                 , F                 , F },
   105     /*Foo<+String>*/ { T     , T                , F                , F                , F                 , F                 , F },
   106     /*Foo<+X1>*/     { T     , T                , F                , F                , F                 , F                 , F },
   107     /*Foo<+X2>*/     { T     , T                , T                , F                , F                 , F                 , F },
   108     /*Foo<+X3>*/     { T     , T                , T                , F                , F                 , F                 , F },
   109     /*Foo<+X4>*/     { T     , T                , T                , F                , F                 , F                 , F },
   110     /*Foo<+X5>*/     { T     , T                , F                , F                , F                 , F                 , F },
   111     /*Foo<+X6>*/     { T     , T                , F                , T                , T                 , I                 , T },
   112     /*Foo<-Object>*/ { T     , T                , F                , F                , F                 , F                 , F },
   113     /*Foo<-Number>*/ { T     , T                , T                , F                , F                 , F                 , F },
   114     /*Foo<-Integer>*/{ T     , T                , T                , F                , F                 , F                 , F },
   115     /*Foo<-Double>*/ { T     , T                , T                , F                , F                 , F                 , F },
   116     /*Foo<-String>*/ { T     , T                , F                , F                , F                 , F                 , F },
   117     /*Foo<-X1>*/     { T     , T                , I                , I                , I                 , I                 , I },
   118     /*Foo<-X2>*/     { T     , T                , I                , F                , F                 , F                 , F },
   119     /*Foo<-X3>*/     { T     , T                , I                , F                , F                 , F                 , F },
   120     /*Foo<-X4>*/     { T     , T                , I                , F                , F                 , F                 , F },
   121     /*Foo<-X5>*/     { T     , T                , I                , F                , F                 , F                 , F },
   122     /*Foo<-X6>*/     { T     , T                , F                , T                , I                 , I                 , T },
   123     /*Foo<?>*/       { T     , T                , T                , T                , T                 , T                 , T }};
   125     GenericTypeWellFormednessTest() {
   126         InstantiableType[] basicTypes = {
   127             new InstantiableType(predef.objectType),
   128             new InstantiableType(NumberType()),
   129             new InstantiableType(box(predef.intType)),
   130             new InstantiableType(box(predef.doubleType)),
   131             new InstantiableType(predef.stringType) };
   133         InstantiableType[] typeVars = new InstantiableType[basicTypes.length + 1];
   134         for (int i = 0 ; i < basicTypes.length ; i++) {
   135            typeVars[i] = new InstantiableType(fac.TypeVariable(basicTypes[i].type));
   136         }
   137         typeVars[typeVars.length - 1] = new InstantiableType(null) {
   138             Type inst(Type clazz) {
   139                 TypeVar tvar = fac.TypeVariable();
   140                 tvar.bound = subst(clazz, Mapping(clazz.getTypeArguments().head, tvar));
   141                 return tvar;
   142             }
   143         };
   145         InstantiableType[] typeArgs = join(InstantiableType.class, basicTypes, typeVars);
   147         InstantiableType[] invariantTypes = new InstantiableType[typeArgs.length];
   148         for (int i = 0 ; i < typeArgs.length ; i++) {
   149            final InstantiableType type1 = typeArgs[i];
   150            invariantTypes[i] = new InstantiableType(typeArgs[i].type) {
   151                Type inst(Type clazz) {
   152                    return subst(clazz, Mapping(clazz.getTypeArguments().head, type1.inst(clazz)));
   153                }
   154             };
   155         }
   157         InstantiableType[] covariantTypes = new InstantiableType[typeArgs.length];
   158         for (int i = 0 ; i < typeArgs.length ; i++) {
   159            final InstantiableType type1 = typeArgs[i];
   160            covariantTypes[i] = new InstantiableType(null) {
   161                Type inst(Type clazz) {
   162                    Type t = fac.Wildcard(BoundKind.EXTENDS, type1.inst(clazz));
   163                    return subst(clazz, Mapping(clazz.getTypeArguments().head, t));
   164                }
   165             };
   166         }
   168         InstantiableType[] contravariantTypes = new InstantiableType[typeArgs.length];
   169         for (int i = 0 ; i < typeArgs.length ; i++) {
   170            final InstantiableType type1 = typeArgs[i];
   171            contravariantTypes[i] = new InstantiableType(null) {
   172                Type inst(Type clazz) {
   173                    Type t = fac.Wildcard(BoundKind.SUPER, type1.inst(clazz));
   174                    return subst(clazz, Mapping(clazz.getTypeArguments().head, t));
   175                }
   176             };
   177         }
   179         InstantiableType[] bivariantTypes = {
   180             new InstantiableType(fac.Wildcard(BoundKind.UNBOUND, predef.objectType)) {
   181                Type inst(Type clazz) {
   182                    return subst(clazz, Mapping(clazz.getTypeArguments().head, type));
   183                }
   184             }
   185         };
   187         rows = join(InstantiableType.class, invariantTypes, covariantTypes, contravariantTypes, bivariantTypes);
   189         Type tv1 = fac.TypeVariable();
   190         Type decl1 = fac.Class(tv1);
   192         Type tv2 = fac.TypeVariable(predef.objectType);
   193         Type decl2 = fac.Class(tv2);
   195         Type tv3 = fac.TypeVariable(NumberType());
   196         Type decl3 = fac.Class(tv3);
   198         TypeVar tv4 = fac.TypeVariable();
   199         Type decl4 = fac.Class(tv4);
   200         tv4.bound = decl4;
   201         tv4.tsym.name = predef.exceptionType.tsym.name;
   203         TypeVar tv5 = fac.TypeVariable();
   204         Type decl5 = fac.Class(tv5);
   205         tv5.bound = subst(decl5, Mapping(tv5, fac.Wildcard(BoundKind.EXTENDS, tv5)));
   207         TypeVar tv6 = fac.TypeVariable();
   208         Type decl6 = fac.Class(tv6);
   209         tv6.bound = subst(decl6, Mapping(tv6, fac.Wildcard(BoundKind.SUPER, tv6)));
   211         TypeVar tv7 = fac.TypeVariable();
   212         Type decl7 = fac.Class(tv7);
   213         tv7.bound = subst(decl7, Mapping(tv7, fac.Wildcard(BoundKind.UNBOUND, predef.objectType)));
   215         columns = new Type[] {
   216             decl1, decl2, decl3, decl4, decl5, decl6, decl7
   217         };
   218     }
   220     void test() {
   221         for (int i = 0; i < rows.length ; i++) {
   222             for (int j = 0; j < columns.length ; j++) {
   223                 Type decl = columns[j];
   224                 Type inst = rows[i].inst(decl);
   225                 if (isValidInstantiation[i][j] != Result.IGNORE) {
   226                     executedCount++;
   227                     assertValidGenericType(inst, isValidInstantiation[i][j].value);
   228                 } else {
   229                     ignoredCount++;
   230                 }
   231             }
   232         }
   233     }
   235     Type NumberType() {
   236         Symbol s = box(predef.intType).tsym;
   237         s.complete();
   238         return ((ClassType)s.type).supertype_field;
   239     }
   241     @SuppressWarnings("unchecked")
   242     <T> T[] join(Class<T> type, T[]... args) {
   243         int totalLength = 0;
   244         for (T[] arr : args) {
   245             totalLength += arr.length;
   246         }
   247         T[] new_arr = (T[])Array.newInstance(type, totalLength);
   248         int idx = 0;
   249         for (T[] arr : args) {
   250             System.arraycopy(arr, 0, new_arr, idx, arr.length);
   251             idx += arr.length;
   252         }
   253         return new_arr;
   254     }
   256     public static void main(String[] args) {
   257         new GenericTypeWellFormednessTest().test();
   258         System.out.println("Executed checks : " + executedCount);
   259         System.out.println("Ignored checks : " + ignoredCount);
   260     }
   261 }

mercurial