26 * @bug 8002099 |
26 * @bug 8002099 |
27 * @summary Add support for intersection types in cast expression |
27 * @summary Add support for intersection types in cast expression |
28 */ |
28 */ |
29 |
29 |
30 import com.sun.source.util.JavacTask; |
30 import com.sun.source.util.JavacTask; |
31 import com.sun.tools.javac.util.List; |
|
32 import com.sun.tools.javac.util.ListBuffer; |
31 import com.sun.tools.javac.util.ListBuffer; |
33 import java.net.URI; |
32 import java.net.URI; |
|
33 import java.util.ArrayList; |
34 import java.util.Arrays; |
34 import java.util.Arrays; |
|
35 import java.util.List; |
35 import javax.tools.Diagnostic; |
36 import javax.tools.Diagnostic; |
36 import javax.tools.JavaCompiler; |
37 import javax.tools.JavaCompiler; |
37 import javax.tools.JavaFileObject; |
38 import javax.tools.JavaFileObject; |
38 import javax.tools.SimpleJavaFileObject; |
39 import javax.tools.SimpleJavaFileObject; |
39 import javax.tools.StandardJavaFileManager; |
40 import javax.tools.StandardJavaFileManager; |
43 |
44 |
44 static int checkCount = 0; |
45 static int checkCount = 0; |
45 |
46 |
46 enum BoundKind { |
47 enum BoundKind { |
47 INTF, |
48 INTF, |
48 CLASS, |
49 CLASS; |
49 SAM, |
|
50 ZAM; |
|
51 } |
50 } |
52 |
51 |
53 enum MethodKind { |
52 enum MethodKind { |
54 NONE, |
53 NONE(false), |
55 ABSTRACT, |
54 ABSTRACT_M(true), |
56 DEFAULT; |
55 DEFAULT_M(false), |
|
56 ABSTRACT_G(true), |
|
57 DEFAULT_G(false); |
|
58 |
|
59 boolean isAbstract; |
|
60 |
|
61 MethodKind(boolean isAbstract) { |
|
62 this.isAbstract = isAbstract; |
|
63 } |
57 } |
64 } |
58 |
65 |
59 enum TypeKind { |
66 enum TypeKind { |
60 A("interface A { }\n", "A", BoundKind.ZAM), |
67 A("interface A { }\n", "A", BoundKind.INTF, MethodKind.NONE), |
61 B("interface B { default void m() { } }\n", "B", BoundKind.ZAM), |
68 B("interface B { default void m() { } }\n", "B", BoundKind.INTF, MethodKind.DEFAULT_M), |
62 C("interface C { void m(); }\n", "C", BoundKind.SAM), |
69 C("interface C { void m(); }\n", "C", BoundKind.INTF, MethodKind.ABSTRACT_M), |
63 D("interface D extends B { }\n", "D", BoundKind.ZAM), |
70 D("interface D extends B { }\n", "D", BoundKind.INTF, MethodKind.DEFAULT_M), |
64 E("interface E extends C { }\n", "E", BoundKind.SAM), |
71 E("interface E extends C { }\n", "E", BoundKind.INTF, MethodKind.ABSTRACT_M), |
65 F("interface F extends C { void g(); }\n", "F", BoundKind.INTF), |
72 F("interface F extends C { void g(); }\n", "F", BoundKind.INTF, MethodKind.ABSTRACT_G, MethodKind.ABSTRACT_M), |
66 G("interface G extends B { void g(); }\n", "G", BoundKind.SAM), |
73 G("interface G extends B { void g(); }\n", "G", BoundKind.INTF, MethodKind.ABSTRACT_G, MethodKind.DEFAULT_M), |
67 H("interface H extends A { void g(); }\n", "H", BoundKind.SAM), |
74 H("interface H extends A { void g(); }\n", "H", BoundKind.INTF, MethodKind.ABSTRACT_G), |
68 OBJECT("", "Object", BoundKind.CLASS), |
75 OBJECT("", "Object", BoundKind.CLASS), |
69 STRING("", "String", BoundKind.CLASS); |
76 STRING("", "String", BoundKind.CLASS); |
70 |
77 |
71 String declStr; |
78 String declStr; |
72 String typeStr; |
79 String typeStr; |
73 BoundKind boundKind; |
80 BoundKind boundKind; |
74 |
81 MethodKind[] methodKinds; |
75 private TypeKind(String declStr, String typeStr, BoundKind boundKind) { |
82 |
|
83 private TypeKind(String declStr, String typeStr, BoundKind boundKind, MethodKind... methodKinds) { |
76 this.declStr = declStr; |
84 this.declStr = declStr; |
77 this.typeStr = typeStr; |
85 this.typeStr = typeStr; |
78 this.boundKind = boundKind; |
86 this.boundKind = boundKind; |
|
87 this.methodKinds = methodKinds; |
79 } |
88 } |
80 |
89 |
81 boolean compatibleSupertype(TypeKind tk) { |
90 boolean compatibleSupertype(TypeKind tk) { |
82 if (tk == this) return true; |
91 if (tk == this) return true; |
83 switch (tk) { |
92 switch (tk) { |
261 checkCount++; |
270 checkCount++; |
262 |
271 |
263 boolean errorExpected = !cInfo.wellFormed(); |
272 boolean errorExpected = !cInfo.wellFormed(); |
264 |
273 |
265 if (ek.isFunctional) { |
274 if (ek.isFunctional) { |
266 //first bound must be a SAM |
275 List<MethodKind> mks = new ArrayList<>(); |
267 errorExpected |= cInfo.types[0].boundKind != BoundKind.SAM; |
276 for (TypeKind tk : cInfo.types) { |
268 if (cInfo.types.length > 1) { |
277 if (tk.boundKind == BoundKind.CLASS) { |
269 //additional bounds must be ZAMs |
278 errorExpected = true; |
270 for (int i = 1; i < cInfo.types.length; i++) { |
279 break; |
271 errorExpected |= cInfo.types[i].boundKind != BoundKind.ZAM; |
280 } else { |
272 } |
281 mks = mergeMethods(mks, Arrays.asList(tk.methodKinds)); |
273 } |
282 } |
|
283 } |
|
284 int abstractCount = 0; |
|
285 for (MethodKind mk : mks) { |
|
286 if (mk.isAbstract) { |
|
287 abstractCount++; |
|
288 } |
|
289 } |
|
290 errorExpected |= abstractCount != 1; |
274 } |
291 } |
275 |
292 |
276 if (errorExpected != diagChecker.errorFound) { |
293 if (errorExpected != diagChecker.errorFound) { |
277 throw new Error("invalid diagnostics for source:\n" + |
294 throw new Error("invalid diagnostics for source:\n" + |
278 source.getCharContent(true) + |
295 source.getCharContent(true) + |
279 "\nFound error: " + diagChecker.errorFound + |
296 "\nFound error: " + diagChecker.errorFound + |
280 "\nExpected error: " + errorExpected); |
297 "\nExpected error: " + errorExpected); |
281 } |
298 } |
282 } |
299 } |
283 |
300 |
|
301 List<MethodKind> mergeMethods(List<MethodKind> l1, List<MethodKind> l2) { |
|
302 List<MethodKind> mergedMethods = new ArrayList<>(l1); |
|
303 for (MethodKind mk2 : l2) { |
|
304 boolean add = !mergedMethods.contains(mk2); |
|
305 switch (mk2) { |
|
306 case ABSTRACT_G: |
|
307 add = add && !mergedMethods.contains(MethodKind.DEFAULT_G); |
|
308 break; |
|
309 case ABSTRACT_M: |
|
310 add = add && !mergedMethods.contains(MethodKind.DEFAULT_M); |
|
311 break; |
|
312 case DEFAULT_G: |
|
313 mergedMethods.remove(MethodKind.ABSTRACT_G); |
|
314 case DEFAULT_M: |
|
315 mergedMethods.remove(MethodKind.ABSTRACT_M); |
|
316 case NONE: |
|
317 add = false; |
|
318 break; |
|
319 } |
|
320 if (add) { |
|
321 mergedMethods.add(mk2); |
|
322 } |
|
323 } |
|
324 return mergedMethods; |
|
325 } |
|
326 |
284 static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { |
327 static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { |
285 |
328 |
286 boolean errorFound; |
329 boolean errorFound; |
287 |
330 |
288 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { |
331 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { |