test/tools/javac/generics/diamond/7030150/GenericConstructorAndDiamondTest.java

Tue, 29 Mar 2011 16:40:51 +0100

author
mcimadamore
date
Tue, 29 Mar 2011 16:40:51 +0100
changeset 950
f5b5112ee1cc
child 993
4caf17560ae0
permissions
-rw-r--r--

7030150: Type inference for generic instance creation failed for formal type parameter
Summary: Problem when explicit generic constructor type-arguments are used in conjunction with diamond
Reviewed-by: jjg

mcimadamore@950 1 /*
mcimadamore@950 2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
mcimadamore@950 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mcimadamore@950 4 *
mcimadamore@950 5 * This code is free software; you can redistribute it and/or modify it
mcimadamore@950 6 * under the terms of the GNU General Public License version 2 only, as
mcimadamore@950 7 * published by the Free Software Foundation.
mcimadamore@950 8 *
mcimadamore@950 9 * This code is distributed in the hope that it will be useful, but WITHOUT
mcimadamore@950 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mcimadamore@950 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mcimadamore@950 12 * version 2 for more details (a copy is included in the LICENSE file that
mcimadamore@950 13 * accompanied this code).
mcimadamore@950 14 *
mcimadamore@950 15 * You should have received a copy of the GNU General Public License version
mcimadamore@950 16 * 2 along with this work; if not, write to the Free Software Foundation,
mcimadamore@950 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mcimadamore@950 18 *
mcimadamore@950 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mcimadamore@950 20 * or visit www.oracle.com if you need additional information or have any
mcimadamore@950 21 * questions.
mcimadamore@950 22 */
mcimadamore@950 23
mcimadamore@950 24 /*
mcimadamore@950 25 * @test
mcimadamore@950 26 * @bug 7030150
mcimadamore@950 27 * @summary Type inference for generic instance creation failed for formal type parameter
mcimadamore@950 28 */
mcimadamore@950 29
mcimadamore@950 30 import com.sun.source.util.JavacTask;
mcimadamore@950 31 import java.net.URI;
mcimadamore@950 32 import java.util.Arrays;
mcimadamore@950 33 import javax.tools.Diagnostic;
mcimadamore@950 34 import javax.tools.JavaCompiler;
mcimadamore@950 35 import javax.tools.JavaFileObject;
mcimadamore@950 36 import javax.tools.SimpleJavaFileObject;
mcimadamore@950 37 import javax.tools.StandardJavaFileManager;
mcimadamore@950 38 import javax.tools.ToolProvider;
mcimadamore@950 39
mcimadamore@950 40 public class GenericConstructorAndDiamondTest {
mcimadamore@950 41
mcimadamore@950 42 enum BoundKind {
mcimadamore@950 43 NO_BOUND(""),
mcimadamore@950 44 STRING_BOUND("extends String"),
mcimadamore@950 45 INTEGER_BOUND("extends Integer");
mcimadamore@950 46
mcimadamore@950 47 String boundStr;
mcimadamore@950 48
mcimadamore@950 49 private BoundKind(String boundStr) {
mcimadamore@950 50 this.boundStr = boundStr;
mcimadamore@950 51 }
mcimadamore@950 52
mcimadamore@950 53 boolean matches(TypeArgumentKind tak) {
mcimadamore@950 54 switch (tak) {
mcimadamore@950 55 case NONE: return true;
mcimadamore@950 56 case STRING: return this != INTEGER_BOUND;
mcimadamore@950 57 case INTEGER: return this != STRING_BOUND;
mcimadamore@950 58 default: return false;
mcimadamore@950 59 }
mcimadamore@950 60 }
mcimadamore@950 61 }
mcimadamore@950 62
mcimadamore@950 63 enum ConstructorKind {
mcimadamore@950 64 NON_GENERIC("Foo(Object o) {}"),
mcimadamore@950 65 GENERIC_NO_BOUND("<T> Foo(T t) {}"),
mcimadamore@950 66 GENERIC_STRING_BOUND("<T extends String> Foo(T t) {}"),
mcimadamore@950 67 GENERIC_INTEGER_BOUND("<T extends Integer> Foo(T t) {}");
mcimadamore@950 68
mcimadamore@950 69 String constrStr;
mcimadamore@950 70
mcimadamore@950 71 private ConstructorKind(String constrStr) {
mcimadamore@950 72 this.constrStr = constrStr;
mcimadamore@950 73 }
mcimadamore@950 74
mcimadamore@950 75 boolean matches(ArgumentKind ak) {
mcimadamore@950 76 switch (ak) {
mcimadamore@950 77 case STRING: return this != GENERIC_INTEGER_BOUND;
mcimadamore@950 78 case INTEGER: return this != GENERIC_STRING_BOUND;
mcimadamore@950 79 default: return false;
mcimadamore@950 80 }
mcimadamore@950 81 }
mcimadamore@950 82 }
mcimadamore@950 83
mcimadamore@950 84 enum TypeArgArity {
mcimadamore@950 85 ONE(1),
mcimadamore@950 86 TWO(2),
mcimadamore@950 87 THREE(3);
mcimadamore@950 88
mcimadamore@950 89 int n;
mcimadamore@950 90
mcimadamore@950 91 private TypeArgArity(int n) {
mcimadamore@950 92 this.n = n;
mcimadamore@950 93 }
mcimadamore@950 94 }
mcimadamore@950 95
mcimadamore@950 96 enum TypeArgumentKind {
mcimadamore@950 97 NONE(""),
mcimadamore@950 98 STRING("String"),
mcimadamore@950 99 INTEGER("Integer");
mcimadamore@950 100
mcimadamore@950 101 String typeargStr;
mcimadamore@950 102
mcimadamore@950 103 private TypeArgumentKind(String typeargStr) {
mcimadamore@950 104 this.typeargStr = typeargStr;
mcimadamore@950 105 }
mcimadamore@950 106
mcimadamore@950 107 String getArgs(TypeArgArity arity) {
mcimadamore@950 108 if (this == NONE) return "";
mcimadamore@950 109 else {
mcimadamore@950 110 StringBuilder buf = new StringBuilder();
mcimadamore@950 111 String sep = "";
mcimadamore@950 112 for (int i = 0 ; i < arity.n ; i++) {
mcimadamore@950 113 buf.append(sep);
mcimadamore@950 114 buf.append(typeargStr);
mcimadamore@950 115 sep = ",";
mcimadamore@950 116 }
mcimadamore@950 117 return "<" + buf.toString() + ">";
mcimadamore@950 118 }
mcimadamore@950 119 }
mcimadamore@950 120
mcimadamore@950 121 boolean matches(ArgumentKind ak) {
mcimadamore@950 122 switch (ak) {
mcimadamore@950 123 case STRING: return this != INTEGER;
mcimadamore@950 124 case INTEGER: return this != STRING;
mcimadamore@950 125 default: return false;
mcimadamore@950 126 }
mcimadamore@950 127 }
mcimadamore@950 128 }
mcimadamore@950 129
mcimadamore@950 130 enum ArgumentKind {
mcimadamore@950 131 STRING("\"\""),
mcimadamore@950 132 INTEGER("1");
mcimadamore@950 133
mcimadamore@950 134 String argStr;
mcimadamore@950 135
mcimadamore@950 136 private ArgumentKind(String argStr) {
mcimadamore@950 137 this.argStr = argStr;
mcimadamore@950 138 }
mcimadamore@950 139 }
mcimadamore@950 140
mcimadamore@950 141 public static void main(String... args) throws Exception {
mcimadamore@950 142
mcimadamore@950 143 //create default shared JavaCompiler - reused across multiple compilations
mcimadamore@950 144 JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
mcimadamore@950 145 StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
mcimadamore@950 146
mcimadamore@950 147 for (BoundKind boundKind : BoundKind.values()) {
mcimadamore@950 148 for (ConstructorKind constructorKind : ConstructorKind.values()) {
mcimadamore@950 149 for (TypeArgumentKind declArgKind : TypeArgumentKind.values()) {
mcimadamore@950 150 for (TypeArgArity arity : TypeArgArity.values()) {
mcimadamore@950 151 for (TypeArgumentKind useArgKind : TypeArgumentKind.values()) {
mcimadamore@950 152 for (ArgumentKind argKind : ArgumentKind.values()) {
mcimadamore@950 153 new GenericConstructorAndDiamondTest(boundKind, constructorKind,
mcimadamore@950 154 declArgKind, arity, useArgKind, argKind).run(comp, fm);
mcimadamore@950 155 }
mcimadamore@950 156 }
mcimadamore@950 157 }
mcimadamore@950 158 }
mcimadamore@950 159 }
mcimadamore@950 160 }
mcimadamore@950 161 }
mcimadamore@950 162
mcimadamore@950 163 BoundKind boundKind;
mcimadamore@950 164 ConstructorKind constructorKind;
mcimadamore@950 165 TypeArgumentKind declTypeArgumentKind;
mcimadamore@950 166 TypeArgArity useTypeArgArity;
mcimadamore@950 167 TypeArgumentKind useTypeArgumentKind;
mcimadamore@950 168 ArgumentKind argumentKind;
mcimadamore@950 169 JavaSource source;
mcimadamore@950 170 DiagnosticChecker diagChecker;
mcimadamore@950 171
mcimadamore@950 172 GenericConstructorAndDiamondTest(BoundKind boundKind, ConstructorKind constructorKind,
mcimadamore@950 173 TypeArgumentKind declTypeArgumentKind, TypeArgArity useTypeArgArity,
mcimadamore@950 174 TypeArgumentKind useTypeArgumentKind, ArgumentKind argumentKind) {
mcimadamore@950 175 this.boundKind = boundKind;
mcimadamore@950 176 this.constructorKind = constructorKind;
mcimadamore@950 177 this.declTypeArgumentKind = declTypeArgumentKind;
mcimadamore@950 178 this.useTypeArgArity = useTypeArgArity;
mcimadamore@950 179 this.useTypeArgumentKind = useTypeArgumentKind;
mcimadamore@950 180 this.argumentKind = argumentKind;
mcimadamore@950 181 this.source = new JavaSource();
mcimadamore@950 182 this.diagChecker = new DiagnosticChecker();
mcimadamore@950 183 }
mcimadamore@950 184
mcimadamore@950 185 class JavaSource extends SimpleJavaFileObject {
mcimadamore@950 186
mcimadamore@950 187 String template = "class Foo<X #BK> {\n" +
mcimadamore@950 188 "#CK\n" +
mcimadamore@950 189 "}\n" +
mcimadamore@950 190 "class Test {\n" +
mcimadamore@950 191 "void test() {\n" +
mcimadamore@950 192 "Foo#TA1 f = new #TA2 Foo<>(#A);\n" +
mcimadamore@950 193 "}\n" +
mcimadamore@950 194 "}\n";
mcimadamore@950 195
mcimadamore@950 196 String source;
mcimadamore@950 197
mcimadamore@950 198 public JavaSource() {
mcimadamore@950 199 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
mcimadamore@950 200 source = template.replace("#BK", boundKind.boundStr).
mcimadamore@950 201 replace("#CK", constructorKind.constrStr)
mcimadamore@950 202 .replace("#TA1", declTypeArgumentKind.getArgs(TypeArgArity.ONE))
mcimadamore@950 203 .replace("#TA2", useTypeArgumentKind.getArgs(useTypeArgArity))
mcimadamore@950 204 .replace("#A", argumentKind.argStr);
mcimadamore@950 205 }
mcimadamore@950 206
mcimadamore@950 207 @Override
mcimadamore@950 208 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
mcimadamore@950 209 return source;
mcimadamore@950 210 }
mcimadamore@950 211 }
mcimadamore@950 212
mcimadamore@950 213 void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
mcimadamore@950 214 JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
mcimadamore@950 215 null, null, Arrays.asList(source));
mcimadamore@950 216 ct.analyze();
mcimadamore@950 217 check();
mcimadamore@950 218 }
mcimadamore@950 219
mcimadamore@950 220 void check() {
mcimadamore@950 221 boolean badActual = !constructorKind.matches(argumentKind);
mcimadamore@950 222
mcimadamore@950 223 boolean badArity = constructorKind != ConstructorKind.NON_GENERIC &&
mcimadamore@950 224 useTypeArgumentKind != TypeArgumentKind.NONE &&
mcimadamore@950 225 useTypeArgArity != TypeArgArity.ONE;
mcimadamore@950 226
mcimadamore@950 227 boolean badMethodTypeArg = constructorKind != ConstructorKind.NON_GENERIC &&
mcimadamore@950 228 !useTypeArgumentKind.matches(argumentKind);
mcimadamore@950 229
mcimadamore@950 230 boolean badGenericType = !boundKind.matches(declTypeArgumentKind);
mcimadamore@950 231
mcimadamore@950 232 boolean shouldFail = badActual || badArity || badMethodTypeArg || badGenericType;
mcimadamore@950 233
mcimadamore@950 234 if (shouldFail != diagChecker.errorFound) {
mcimadamore@950 235 throw new Error("invalid diagnostics for source:\n" +
mcimadamore@950 236 source.getCharContent(true) +
mcimadamore@950 237 "\nFound error: " + diagChecker.errorFound +
mcimadamore@950 238 "\nExpected error: " + shouldFail);
mcimadamore@950 239 }
mcimadamore@950 240 }
mcimadamore@950 241
mcimadamore@950 242 static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
mcimadamore@950 243
mcimadamore@950 244 boolean errorFound;
mcimadamore@950 245
mcimadamore@950 246 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
mcimadamore@950 247 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
mcimadamore@950 248 errorFound = true;
mcimadamore@950 249 }
mcimadamore@950 250 }
mcimadamore@950 251 }
mcimadamore@950 252 }

mercurial