Mon, 17 Oct 2011 12:54:33 +0100
7097436: Project Coin: duplicate varargs warnings on method annotated with @SafeVarargs
Summary: Duplicate aliasing check during subtyping leads to spurious varargs diagnostic
Reviewed-by: jjg
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 }