test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java

Tue, 14 May 2013 11:11:09 -0700

author
rfield
date
Tue, 14 May 2013 11:11:09 -0700
changeset 1752
c09b7234cded
parent 1520
5c956be64b9e
child 2000
4a6acc42c3a1
permissions
-rw-r--r--

8012556: Implement lambda methods on interfaces as static
8006140: Javac NPE compiling Lambda expression on initialization expression of static field in interface
Summary: Lambdas occurring in static contexts or those not needing instance information should be generated into static methods. This has long been the case for classes. However, as a work-around to the lack of support for statics on interfaces, interface lambda methods have been generated into default methods. For lambdas in interface static contexts (fields and static methods) this causes an NPE in javac because there is no 'this'. MethodHandles now support static methods on interfaces. This changeset allows lambda methods to be generated as static interface methods. An existing bug in Hotspot (8013875) is exposed in a test when the "-esa" flag is used. This test and another test that already exposed this bug have been marked with @ignore.
Reviewed-by: mcimadamore

mcimadamore@1415 1 /*
vromero@1482 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
mcimadamore@1415 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mcimadamore@1415 4 *
mcimadamore@1415 5 * This code is free software; you can redistribute it and/or modify it
mcimadamore@1415 6 * under the terms of the GNU General Public License version 2 only, as
mcimadamore@1415 7 * published by the Free Software Foundation.
mcimadamore@1415 8 *
mcimadamore@1415 9 * This code is distributed in the hope that it will be useful, but WITHOUT
mcimadamore@1415 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mcimadamore@1415 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mcimadamore@1415 12 * version 2 for more details (a copy is included in the LICENSE file that
mcimadamore@1415 13 * accompanied this code).
mcimadamore@1415 14 *
mcimadamore@1415 15 * You should have received a copy of the GNU General Public License version
mcimadamore@1415 16 * 2 along with this work; if not, write to the Free Software Foundation,
mcimadamore@1415 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mcimadamore@1415 18 *
mcimadamore@1415 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mcimadamore@1415 20 * or visit www.oracle.com if you need additional information or have any
mcimadamore@1415 21 * questions.
mcimadamore@1415 22 */
mcimadamore@1415 23
mcimadamore@1415 24 /*
mcimadamore@1415 25 * @test
vromero@1520 26 * @bug 8003280 8006694
mcimadamore@1415 27 * @summary Add lambda tests
mcimadamore@1415 28 * Automatic test for checking correctness of structural most specific test routine
vromero@1520 29 * temporarily workaround combo tests are causing time out in several platforms
vromero@1482 30 * @library ../../lib
vromero@1482 31 * @build JavacTestingAbstractThreadedTest
vromero@1520 32 * @run main/othervm/timeout=600 StructuralMostSpecificTest
mcimadamore@1415 33 */
mcimadamore@1415 34
vromero@1520 35 // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047)
vromero@1520 36 // see JDK-8006746
vromero@1520 37
vromero@1482 38 import java.net.URI;
vromero@1482 39 import java.util.Arrays;
vromero@1482 40 import javax.tools.Diagnostic;
vromero@1482 41 import javax.tools.JavaFileObject;
vromero@1482 42 import javax.tools.SimpleJavaFileObject;
mcimadamore@1415 43 import com.sun.source.util.JavacTask;
mcimadamore@1415 44 import com.sun.tools.javac.api.ClientCodeWrapper;
mcimadamore@1415 45 import com.sun.tools.javac.util.JCDiagnostic;
mcimadamore@1415 46
vromero@1482 47 public class StructuralMostSpecificTest
vromero@1482 48 extends JavacTestingAbstractThreadedTest
vromero@1482 49 implements Runnable {
mcimadamore@1415 50
mcimadamore@1415 51 enum RetTypeKind {
mcimadamore@1415 52 SHORT("short"),
mcimadamore@1415 53 INT("int"),
mcimadamore@1415 54 OBJECT("Object"),
mcimadamore@1415 55 INTEGER("Integer"),
mcimadamore@1415 56 VOID("void"),
mcimadamore@1415 57 J_L_VOID("Void");
mcimadamore@1415 58
mcimadamore@1415 59 String retTypeStr;
mcimadamore@1415 60
mcimadamore@1415 61 RetTypeKind(String retTypeStr) {
mcimadamore@1415 62 this.retTypeStr = retTypeStr;
mcimadamore@1415 63 }
mcimadamore@1415 64
mcimadamore@1415 65 boolean moreSpecificThan(RetTypeKind rk) {
mcimadamore@1415 66 return moreSpecificThan[this.ordinal()][rk.ordinal()];
mcimadamore@1415 67 }
mcimadamore@1415 68
mcimadamore@1415 69 static boolean[][] moreSpecificThan = {
mcimadamore@1415 70 // SHORT | INT | OBJECT | INTEGER | VOID | J_L_VOID
mcimadamore@1415 71 /* SHORT */ { true , true , true , false , false , false },
mcimadamore@1415 72 /* INT */ { false , true , true , true , false , false },
mcimadamore@1415 73 /* OBJECT */ { false , false , true , false , false , false },
mcimadamore@1415 74 /* INTEGER */ { false , false , true , true , false , false },
mcimadamore@1415 75 /* VOID */ { false , false , false , false , true , true },
mcimadamore@1415 76 /* J_L_VOID */{ false , false , true , false , false , true } };
mcimadamore@1415 77 }
mcimadamore@1415 78
mcimadamore@1415 79 enum ArgTypeKind {
mcimadamore@1415 80 SHORT("short"),
mcimadamore@1415 81 INT("int"),
mcimadamore@1415 82 BOOLEAN("boolean"),
mcimadamore@1415 83 OBJECT("Object"),
mcimadamore@1415 84 INTEGER("Integer"),
mcimadamore@1415 85 DOUBLE("Double");
mcimadamore@1415 86
mcimadamore@1415 87 String argTypeStr;
mcimadamore@1415 88
mcimadamore@1415 89 ArgTypeKind(String typeStr) {
mcimadamore@1415 90 this.argTypeStr = typeStr;
mcimadamore@1415 91 }
mcimadamore@1415 92 }
mcimadamore@1415 93
mcimadamore@1415 94 enum ExceptionKind {
mcimadamore@1415 95 NONE(""),
mcimadamore@1415 96 EXCEPTION("throws Exception"),
mcimadamore@1415 97 SQL_EXCEPTION("throws java.sql.SQLException"),
mcimadamore@1415 98 IO_EXCEPTION("throws java.io.IOException");
mcimadamore@1415 99
mcimadamore@1415 100 String exceptionStr;
mcimadamore@1415 101
mcimadamore@1415 102 ExceptionKind(String exceptionStr) {
mcimadamore@1415 103 this.exceptionStr = exceptionStr;
mcimadamore@1415 104 }
mcimadamore@1415 105 }
mcimadamore@1415 106
mcimadamore@1415 107 enum LambdaReturnKind {
mcimadamore@1415 108 VOID("return;"),
mcimadamore@1415 109 SHORT("return (short)0;"),
mcimadamore@1415 110 INT("return 0;"),
vromero@1482 111 INTEGER("return (Integer)null;"),
mcimadamore@1415 112 NULL("return null;");
mcimadamore@1415 113
mcimadamore@1415 114 String retStr;
mcimadamore@1415 115
mcimadamore@1415 116 LambdaReturnKind(String retStr) {
mcimadamore@1415 117 this.retStr = retStr;
mcimadamore@1415 118 }
mcimadamore@1415 119
mcimadamore@1415 120 boolean compatibleWith(RetTypeKind rk) {
mcimadamore@1415 121 return compatibleWith[rk.ordinal()][ordinal()];
mcimadamore@1415 122 }
mcimadamore@1415 123
mcimadamore@1415 124 static boolean[][] compatibleWith = {
mcimadamore@1415 125 // VOID | SHORT | INT | INTEGER | NULL
mcimadamore@1415 126 /* SHORT */ { false , true , false , false , false },
mcimadamore@1415 127 /* INT */ { false , true , true , true , false },
mcimadamore@1415 128 /* OBJECT */ { false , true , true , true , true },
mcimadamore@1415 129 /* INTEGER */ { false , false , true , true , true },
mcimadamore@1415 130 /* VOID */ { true , false , false , false , false },
mcimadamore@1415 131 /* J_L_VOID */{ false , false , false , false , true } };
mcimadamore@1415 132
mcimadamore@1415 133 boolean needsConversion(RetTypeKind rk) {
mcimadamore@1415 134 return needsConversion[rk.ordinal()][ordinal()];
mcimadamore@1415 135 }
mcimadamore@1415 136
mcimadamore@1415 137 static boolean[][] needsConversion = {
mcimadamore@1415 138 // VOID | SHORT | INT | INTEGER | NULL
mcimadamore@1415 139 /* SHORT */ { false , false , false , false , false },
mcimadamore@1415 140 /* INT */ { false , false , false , true , false },
mcimadamore@1415 141 /* OBJECT */ { false , true , true , false , false },
mcimadamore@1415 142 /* INTEGER */ { false , false , true , false , false },
mcimadamore@1415 143 /* VOID */ { false , false , false , false , false },
mcimadamore@1415 144 /* J_L_VOID */{ true , false , false , false , false } };
mcimadamore@1415 145 }
mcimadamore@1415 146
mcimadamore@1415 147 public static void main(String... args) throws Exception {
mcimadamore@1415 148 for (LambdaReturnKind lrk : LambdaReturnKind.values()) {
mcimadamore@1415 149 for (RetTypeKind rk1 : RetTypeKind.values()) {
mcimadamore@1415 150 for (RetTypeKind rk2 : RetTypeKind.values()) {
mcimadamore@1415 151 for (ExceptionKind ek1 : ExceptionKind.values()) {
mcimadamore@1415 152 for (ExceptionKind ek2 : ExceptionKind.values()) {
mcimadamore@1415 153 for (ArgTypeKind ak11 : ArgTypeKind.values()) {
mcimadamore@1415 154 for (ArgTypeKind ak12 : ArgTypeKind.values()) {
vromero@1482 155 pool.execute(
vromero@1482 156 new StructuralMostSpecificTest(lrk, rk1,
vromero@1482 157 rk2, ek1, ek2, ak11, ak12));
mcimadamore@1415 158 }
mcimadamore@1415 159 }
mcimadamore@1415 160 }
mcimadamore@1415 161 }
mcimadamore@1415 162 }
mcimadamore@1415 163 }
mcimadamore@1415 164 }
vromero@1482 165
vromero@1482 166 checkAfterExec();
mcimadamore@1415 167 }
mcimadamore@1415 168
mcimadamore@1415 169 LambdaReturnKind lrk;
mcimadamore@1415 170 RetTypeKind rt1, rt2;
mcimadamore@1415 171 ArgTypeKind ak1, ak2;
mcimadamore@1415 172 ExceptionKind ek1, ek2;
mcimadamore@1415 173 JavaSource source;
mcimadamore@1415 174 DiagnosticChecker diagChecker;
mcimadamore@1415 175
mcimadamore@1415 176 StructuralMostSpecificTest(LambdaReturnKind lrk, RetTypeKind rt1, RetTypeKind rt2,
mcimadamore@1415 177 ExceptionKind ek1, ExceptionKind ek2, ArgTypeKind ak1, ArgTypeKind ak2) {
mcimadamore@1415 178 this.lrk = lrk;
mcimadamore@1415 179 this.rt1 = rt1;
mcimadamore@1415 180 this.rt2 = rt2;
mcimadamore@1415 181 this.ek1 = ek1;
mcimadamore@1415 182 this.ek2 = ek2;
mcimadamore@1415 183 this.ak1 = ak1;
mcimadamore@1415 184 this.ak2 = ak2;
mcimadamore@1415 185 this.source = new JavaSource();
mcimadamore@1415 186 this.diagChecker = new DiagnosticChecker();
mcimadamore@1415 187 }
mcimadamore@1415 188
mcimadamore@1415 189 class JavaSource extends SimpleJavaFileObject {
mcimadamore@1415 190
mcimadamore@1415 191 String template = "interface SAM1 {\n" +
mcimadamore@1415 192 " #R1 m(#A1 a1) #E1;\n" +
mcimadamore@1415 193 "}\n" +
mcimadamore@1415 194 "interface SAM2 {\n" +
mcimadamore@1415 195 " #R2 m(#A2 a1) #E2;\n" +
mcimadamore@1415 196 "}\n" +
mcimadamore@1415 197 "class Test {\n" +
mcimadamore@1415 198 " void m(SAM1 s) { }\n" +
mcimadamore@1415 199 " void m(SAM2 s) { }\n" +
mcimadamore@1415 200 " { m(x->{ #LR }); }\n" +
mcimadamore@1415 201 "}\n";
mcimadamore@1415 202
mcimadamore@1415 203 String source;
mcimadamore@1415 204
mcimadamore@1415 205 public JavaSource() {
mcimadamore@1415 206 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
mcimadamore@1415 207 source = template.replaceAll("#LR", lrk.retStr)
mcimadamore@1415 208 .replaceAll("#R1", rt1.retTypeStr)
mcimadamore@1415 209 .replaceAll("#R2", rt2.retTypeStr)
mcimadamore@1415 210 .replaceAll("#A1", ak1.argTypeStr)
mcimadamore@1415 211 .replaceAll("#A2", ak2.argTypeStr)
mcimadamore@1415 212 .replaceAll("#E1", ek1.exceptionStr)
mcimadamore@1415 213 .replaceAll("#E2", ek2.exceptionStr);
mcimadamore@1415 214 }
mcimadamore@1415 215
mcimadamore@1415 216 @Override
mcimadamore@1415 217 public CharSequence getCharContent(boolean ignoreEncodingErrors) {
mcimadamore@1415 218 return source;
mcimadamore@1415 219 }
mcimadamore@1415 220 }
mcimadamore@1415 221
vromero@1482 222 public void run() {
vromero@1482 223 JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
mcimadamore@1415 224 Arrays.asList("-XDverboseResolution=all,-predef,-internal,-object-init"),
mcimadamore@1415 225 null, Arrays.asList(source));
mcimadamore@1415 226 try {
mcimadamore@1415 227 ct.analyze();
mcimadamore@1415 228 } catch (Throwable ex) {
vromero@1482 229 throw new
vromero@1482 230 AssertionError("Error thron when analyzing the following source:\n" +
vromero@1482 231 source.getCharContent(true));
mcimadamore@1415 232 }
mcimadamore@1415 233 check();
mcimadamore@1415 234 }
mcimadamore@1415 235
mcimadamore@1415 236 void check() {
vromero@1482 237 checkCount.incrementAndGet();
mcimadamore@1415 238
mcimadamore@1415 239 if (!lrk.compatibleWith(rt1) || !lrk.compatibleWith(rt2))
mcimadamore@1415 240 return;
mcimadamore@1415 241
mcimadamore@1415 242 if (lrk.needsConversion(rt1) != lrk.needsConversion(rt2))
mcimadamore@1415 243 return;
mcimadamore@1415 244
mcimadamore@1415 245 boolean m1MoreSpecific = moreSpecific(rt1, rt2, ek1, ek2, ak1, ak2);
mcimadamore@1415 246 boolean m2MoreSpecific = moreSpecific(rt2, rt1, ek2, ek1, ak2, ak1);
mcimadamore@1415 247
mcimadamore@1415 248 boolean ambiguous = (m1MoreSpecific == m2MoreSpecific);
mcimadamore@1415 249
mcimadamore@1415 250 if (ambiguous != diagChecker.ambiguityFound) {
mcimadamore@1415 251 throw new Error("invalid diagnostics for source:\n" +
mcimadamore@1415 252 source.getCharContent(true) +
mcimadamore@1415 253 "\nAmbiguity found: " + diagChecker.ambiguityFound +
mcimadamore@1415 254 "\nm1 more specific: " + m1MoreSpecific +
mcimadamore@1415 255 "\nm2 more specific: " + m2MoreSpecific +
mcimadamore@1415 256 "\nexpected ambiguity: " + ambiguous);
mcimadamore@1415 257 }
mcimadamore@1415 258
mcimadamore@1415 259 if (!ambiguous) {
mcimadamore@1415 260 String sigToCheck = m1MoreSpecific ? "m(SAM1)" : "m(SAM2)";
mcimadamore@1415 261 if (!sigToCheck.equals(diagChecker.mostSpecificSig)) {
mcimadamore@1415 262 throw new Error("invalid most specific method selected:\n" +
mcimadamore@1415 263 source.getCharContent(true) +
mcimadamore@1415 264 "\nMost specific found: " + diagChecker.mostSpecificSig +
mcimadamore@1415 265 "\nm1 more specific: " + m1MoreSpecific +
mcimadamore@1415 266 "\nm2 more specific: " + m2MoreSpecific);
mcimadamore@1415 267 }
mcimadamore@1415 268 }
mcimadamore@1415 269 }
mcimadamore@1415 270
vromero@1482 271 boolean moreSpecific(RetTypeKind rk1, RetTypeKind rk2, ExceptionKind ek1,
vromero@1482 272 ExceptionKind ek2, ArgTypeKind ak1, ArgTypeKind ak2) {
mcimadamore@1415 273 if (!rk1.moreSpecificThan(rk2))
mcimadamore@1415 274 return false;
mcimadamore@1415 275
mcimadamore@1415 276 if (ak1 != ak2)
mcimadamore@1415 277 return false;
mcimadamore@1415 278
mcimadamore@1415 279 return true;
mcimadamore@1415 280 }
mcimadamore@1415 281
vromero@1482 282 static class DiagnosticChecker
vromero@1482 283 implements javax.tools.DiagnosticListener<JavaFileObject> {
mcimadamore@1415 284
mcimadamore@1415 285 boolean ambiguityFound;
mcimadamore@1415 286 String mostSpecificSig;
mcimadamore@1415 287
mcimadamore@1415 288 public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
mcimadamore@1415 289 try {
mcimadamore@1415 290 if (diagnostic.getKind() == Diagnostic.Kind.ERROR &&
mcimadamore@1415 291 diagnostic.getCode().equals("compiler.err.ref.ambiguous")) {
mcimadamore@1415 292 ambiguityFound = true;
mcimadamore@1415 293 } else if (diagnostic.getKind() == Diagnostic.Kind.NOTE &&
vromero@1482 294 diagnostic.getCode()
vromero@1482 295 .equals("compiler.note.verbose.resolve.multi")) {
mcimadamore@1415 296 ClientCodeWrapper.DiagnosticSourceUnwrapper dsu =
vromero@1482 297 (ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic;
vromero@1482 298 JCDiagnostic.MultilineDiagnostic mdiag =
vromero@1482 299 (JCDiagnostic.MultilineDiagnostic)dsu.d;
mcimadamore@1415 300 int mostSpecificIndex = (Integer)mdiag.getArgs()[2];
vromero@1482 301 mostSpecificSig =
vromero@1482 302 ((JCDiagnostic)mdiag.getSubdiagnostics()
vromero@1482 303 .get(mostSpecificIndex)).getArgs()[1].toString();
mcimadamore@1415 304 }
mcimadamore@1415 305 } catch (RuntimeException t) {
mcimadamore@1415 306 t.printStackTrace();
mcimadamore@1415 307 throw t;
mcimadamore@1415 308 }
mcimadamore@1415 309 }
mcimadamore@1415 310 }
vromero@1482 311
mcimadamore@1415 312 }

mercurial