1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/test/tools/javac/types/GenericTypeWellFormednessTest.java Wed Apr 27 01:34:52 2016 +0800 1.3 @@ -0,0 +1,261 @@ 1.4 +/* 1.5 + * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + */ 1.26 + 1.27 +/* 1.28 + * @test 1.29 + * @bug 7007432 7006109 1.30 + * @summary Test generic types well-formedness 1.31 + * @author mcimadamore 1.32 + * @library . 1.33 + * @run main GenericTypeWellFormednessTest 1.34 + */ 1.35 + 1.36 +import com.sun.tools.javac.code.BoundKind; 1.37 +import com.sun.tools.javac.code.Type; 1.38 +import com.sun.tools.javac.code.Type.*; 1.39 +import com.sun.tools.javac.code.Symbol; 1.40 +import com.sun.tools.javac.code.Symbol.*; 1.41 +import java.lang.reflect.Array; 1.42 + 1.43 +/** 1.44 + * Check parameterized type well-formedness. This test executes a number of checks 1.45 + * in order to establish as to whether an instantiation of a generic type conforms 1.46 + * to the generic class' declared bounds. 1.47 + */ 1.48 +public class GenericTypeWellFormednessTest extends TypeHarness { 1.49 + 1.50 + static int executedCount = 0; 1.51 + static int ignoredCount = 0; 1.52 + 1.53 + InstantiableType[] rows; 1.54 + Type[] columns; 1.55 + 1.56 + static class InstantiableType { 1.57 + protected Type type; 1.58 + 1.59 + public InstantiableType(Type type) { 1.60 + this.type = type; 1.61 + } 1.62 + 1.63 + Type inst(Type clazz) { 1.64 + return type; 1.65 + } 1.66 + } 1.67 + 1.68 + enum Result { 1.69 + /* generic type is well-formed w.r.t. declared bounds */ 1.70 + OK(true), 1.71 + /* generic type is not well-formed w.r.t. declared bounds */ 1.72 + FAIL(false), 1.73 + /* generic type is not well-formed w.r.t. declared bounds according to the JLS 3rd, 1.74 + * but javac allows it (spec for generic type well-formedness is overly restrictive) 1.75 + * See regression test test/tools/generics/wildcards/T5097548.java 1.76 + */ 1.77 + IGNORE(false); 1.78 + 1.79 + boolean value; 1.80 + 1.81 + Result(boolean value) { 1.82 + this.value = value; 1.83 + } 1.84 + } 1.85 + 1.86 + static final Result T = Result.OK; 1.87 + static final Result F = Result.FAIL; 1.88 + static final Result I = Result.IGNORE; 1.89 + 1.90 + /*is a type in 'rows' a valid instantiation for the generic class in 'col' ? */ 1.91 + Result[][] isValidInstantiation = { 1.92 + //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<?>> 1.93 + /*Foo<Object>*/ { T , T , F , F , F , F , F }, 1.94 + /*Foo<Number>*/ { T , T , T , F , F , F , F }, 1.95 + /*Foo<Integer>*/ { T , T , T , F , F , F , F }, 1.96 + /*Foo<Double>*/ { T , T , T , F , F , F , F }, 1.97 + /*Foo<String>*/ { T , T , F , F , F , F , F }, 1.98 + /*Foo<X1>*/ { T , T , F , F , F , F , F }, 1.99 + /*Foo<X2>*/ { T , T , T , F , F , F , F }, 1.100 + /*Foo<X3>*/ { T , T , T , F , F , F , F }, 1.101 + /*Foo<X4>*/ { T , T , T , F , F , F , F }, 1.102 + /*Foo<X5>*/ { T , T , F , F , F , F , F }, 1.103 + /*Foo<X6>*/ { T , T , F , T , T , T , T }, 1.104 + /*Foo<+Object>*/ { T , T , I , I , I , I , I }, 1.105 + /*Foo<+Number>*/ { T , T , T , F , F , F , F }, 1.106 + /*Foo<+Integer>*/{ T , T , T , F , F , F , F }, 1.107 + /*Foo<+Double>*/ { T , T , T , F , F , F , F }, 1.108 + /*Foo<+String>*/ { T , T , F , F , F , F , F }, 1.109 + /*Foo<+X1>*/ { T , T , F , F , F , F , F }, 1.110 + /*Foo<+X2>*/ { T , T , T , F , F , F , F }, 1.111 + /*Foo<+X3>*/ { T , T , T , F , F , F , F }, 1.112 + /*Foo<+X4>*/ { T , T , T , F , F , F , F }, 1.113 + /*Foo<+X5>*/ { T , T , F , F , F , F , F }, 1.114 + /*Foo<+X6>*/ { T , T , F , T , T , I , T }, 1.115 + /*Foo<-Object>*/ { T , T , F , F , F , F , F }, 1.116 + /*Foo<-Number>*/ { T , T , T , F , F , F , F }, 1.117 + /*Foo<-Integer>*/{ T , T , T , F , F , F , F }, 1.118 + /*Foo<-Double>*/ { T , T , T , F , F , F , F }, 1.119 + /*Foo<-String>*/ { T , T , F , F , F , F , F }, 1.120 + /*Foo<-X1>*/ { T , T , I , I , I , I , I }, 1.121 + /*Foo<-X2>*/ { T , T , I , F , F , F , F }, 1.122 + /*Foo<-X3>*/ { T , T , I , F , F , F , F }, 1.123 + /*Foo<-X4>*/ { T , T , I , F , F , F , F }, 1.124 + /*Foo<-X5>*/ { T , T , I , F , F , F , F }, 1.125 + /*Foo<-X6>*/ { T , T , F , T , I , I , T }, 1.126 + /*Foo<?>*/ { T , T , T , T , T , T , T }}; 1.127 + 1.128 + GenericTypeWellFormednessTest() { 1.129 + InstantiableType[] basicTypes = { 1.130 + new InstantiableType(predef.objectType), 1.131 + new InstantiableType(NumberType()), 1.132 + new InstantiableType(box(predef.intType)), 1.133 + new InstantiableType(box(predef.doubleType)), 1.134 + new InstantiableType(predef.stringType) }; 1.135 + 1.136 + InstantiableType[] typeVars = new InstantiableType[basicTypes.length + 1]; 1.137 + for (int i = 0 ; i < basicTypes.length ; i++) { 1.138 + typeVars[i] = new InstantiableType(fac.TypeVariable(basicTypes[i].type)); 1.139 + } 1.140 + typeVars[typeVars.length - 1] = new InstantiableType(null) { 1.141 + Type inst(Type clazz) { 1.142 + TypeVar tvar = fac.TypeVariable(); 1.143 + tvar.bound = subst(clazz, Mapping(clazz.getTypeArguments().head, tvar)); 1.144 + return tvar; 1.145 + } 1.146 + }; 1.147 + 1.148 + InstantiableType[] typeArgs = join(InstantiableType.class, basicTypes, typeVars); 1.149 + 1.150 + InstantiableType[] invariantTypes = new InstantiableType[typeArgs.length]; 1.151 + for (int i = 0 ; i < typeArgs.length ; i++) { 1.152 + final InstantiableType type1 = typeArgs[i]; 1.153 + invariantTypes[i] = new InstantiableType(typeArgs[i].type) { 1.154 + Type inst(Type clazz) { 1.155 + return subst(clazz, Mapping(clazz.getTypeArguments().head, type1.inst(clazz))); 1.156 + } 1.157 + }; 1.158 + } 1.159 + 1.160 + InstantiableType[] covariantTypes = new InstantiableType[typeArgs.length]; 1.161 + for (int i = 0 ; i < typeArgs.length ; i++) { 1.162 + final InstantiableType type1 = typeArgs[i]; 1.163 + covariantTypes[i] = new InstantiableType(null) { 1.164 + Type inst(Type clazz) { 1.165 + Type t = fac.Wildcard(BoundKind.EXTENDS, type1.inst(clazz)); 1.166 + return subst(clazz, Mapping(clazz.getTypeArguments().head, t)); 1.167 + } 1.168 + }; 1.169 + } 1.170 + 1.171 + InstantiableType[] contravariantTypes = new InstantiableType[typeArgs.length]; 1.172 + for (int i = 0 ; i < typeArgs.length ; i++) { 1.173 + final InstantiableType type1 = typeArgs[i]; 1.174 + contravariantTypes[i] = new InstantiableType(null) { 1.175 + Type inst(Type clazz) { 1.176 + Type t = fac.Wildcard(BoundKind.SUPER, type1.inst(clazz)); 1.177 + return subst(clazz, Mapping(clazz.getTypeArguments().head, t)); 1.178 + } 1.179 + }; 1.180 + } 1.181 + 1.182 + InstantiableType[] bivariantTypes = { 1.183 + new InstantiableType(fac.Wildcard(BoundKind.UNBOUND, predef.objectType)) { 1.184 + Type inst(Type clazz) { 1.185 + return subst(clazz, Mapping(clazz.getTypeArguments().head, type)); 1.186 + } 1.187 + } 1.188 + }; 1.189 + 1.190 + rows = join(InstantiableType.class, invariantTypes, covariantTypes, contravariantTypes, bivariantTypes); 1.191 + 1.192 + Type tv1 = fac.TypeVariable(); 1.193 + Type decl1 = fac.Class(tv1); 1.194 + 1.195 + Type tv2 = fac.TypeVariable(predef.objectType); 1.196 + Type decl2 = fac.Class(tv2); 1.197 + 1.198 + Type tv3 = fac.TypeVariable(NumberType()); 1.199 + Type decl3 = fac.Class(tv3); 1.200 + 1.201 + TypeVar tv4 = fac.TypeVariable(); 1.202 + Type decl4 = fac.Class(tv4); 1.203 + tv4.bound = decl4; 1.204 + tv4.tsym.name = predef.exceptionType.tsym.name; 1.205 + 1.206 + TypeVar tv5 = fac.TypeVariable(); 1.207 + Type decl5 = fac.Class(tv5); 1.208 + tv5.bound = subst(decl5, Mapping(tv5, fac.Wildcard(BoundKind.EXTENDS, tv5))); 1.209 + 1.210 + TypeVar tv6 = fac.TypeVariable(); 1.211 + Type decl6 = fac.Class(tv6); 1.212 + tv6.bound = subst(decl6, Mapping(tv6, fac.Wildcard(BoundKind.SUPER, tv6))); 1.213 + 1.214 + TypeVar tv7 = fac.TypeVariable(); 1.215 + Type decl7 = fac.Class(tv7); 1.216 + tv7.bound = subst(decl7, Mapping(tv7, fac.Wildcard(BoundKind.UNBOUND, predef.objectType))); 1.217 + 1.218 + columns = new Type[] { 1.219 + decl1, decl2, decl3, decl4, decl5, decl6, decl7 1.220 + }; 1.221 + } 1.222 + 1.223 + void test() { 1.224 + for (int i = 0; i < rows.length ; i++) { 1.225 + for (int j = 0; j < columns.length ; j++) { 1.226 + Type decl = columns[j]; 1.227 + Type inst = rows[i].inst(decl); 1.228 + if (isValidInstantiation[i][j] != Result.IGNORE) { 1.229 + executedCount++; 1.230 + assertValidGenericType(inst, isValidInstantiation[i][j].value); 1.231 + } else { 1.232 + ignoredCount++; 1.233 + } 1.234 + } 1.235 + } 1.236 + } 1.237 + 1.238 + Type NumberType() { 1.239 + Symbol s = box(predef.intType).tsym; 1.240 + s.complete(); 1.241 + return ((ClassType)s.type).supertype_field; 1.242 + } 1.243 + 1.244 + @SuppressWarnings("unchecked") 1.245 + <T> T[] join(Class<T> type, T[]... args) { 1.246 + int totalLength = 0; 1.247 + for (T[] arr : args) { 1.248 + totalLength += arr.length; 1.249 + } 1.250 + T[] new_arr = (T[])Array.newInstance(type, totalLength); 1.251 + int idx = 0; 1.252 + for (T[] arr : args) { 1.253 + System.arraycopy(arr, 0, new_arr, idx, arr.length); 1.254 + idx += arr.length; 1.255 + } 1.256 + return new_arr; 1.257 + } 1.258 + 1.259 + public static void main(String[] args) { 1.260 + new GenericTypeWellFormednessTest().test(); 1.261 + System.out.println("Executed checks : " + executedCount); 1.262 + System.out.println("Ignored checks : " + ignoredCount); 1.263 + } 1.264 +}