1 /*
2 * Copyright (c) 2024, 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 */
23
24 import jdk.incubator.code.Reflect;
25 import java.util.List;
26
27 /*
28 * @test
29 * @summary Smoke test for non-denotable types in IR type descriptors
30 * @modules jdk.incubator.code
31 * @build DenotableTypesTest
32 * @build CodeReflectionTester
33 * @run main CodeReflectionTester DenotableTypesTest
34 */
35
36 public class DenotableTypesTest {
37 static <X extends Number & Runnable> X m1(X x) { return null; }
38 @Reflect
39 @IR("""
40 func @"test1" ()java.type:"void" -> {
41 %0 : java.type:"java.lang.Number" = constant @null;
42 %1 : java.type:"java.lang.Number" = invoke %0 @java.ref:"DenotableTypesTest::m1(java.lang.Number):java.lang.Number";
43 return;
44 };
45 """)
46 static void test1() {
47 m1(null);
48 }
49
50 @Reflect
51 @IR("""
52 func @"test2" ()java.type:"void" -> {
53 %0 : java.type:"int" = constant @1;
54 %1 : java.type:"java.lang.Integer" = invoke %0 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
55 %2 : java.type:"double" = constant @3.0d;
56 %3 : java.type:"java.lang.Double" = invoke %2 @java.ref:"java.lang.Double::valueOf(double):java.lang.Double";
57 %4 : java.type:"java.util.List<? extends java.lang.Number>" = invoke %1 %3 @java.ref:"java.util.List::of(java.lang.Object, java.lang.Object):java.util.List";
58 return;
59 };
60 """)
61 static void test2() {
62 List.of(1, 3d); // infinite type! (List<Object & Serializable & Comparable<...>>)
63 }
64
65 static <X extends Throwable> X m2(X x) throws X { return null; }
66
67 @Reflect
68 @IR("""
69 func @"test3" ()java.type:"void" -> {
70 %0 : java.type:"java.lang.RuntimeException" = constant @null;
71 %1 : java.type:"java.lang.RuntimeException" = invoke %0 @java.ref:"DenotableTypesTest::m2(java.lang.Throwable):java.lang.Throwable";
72 return;
73 };
74 """)
75 static void test3() { // @@@ cast?
76 m2(null);
77 }
78
79 interface A { }
80 interface B { }
81 static class C implements A, B { }
82 static class D implements A, B { }
83
84 static <Z> Z pick(Z z1, Z z2) { return null; }
85
86 @Reflect
87 @IR("""
88 func @"test4" ()java.type:"void" -> {
89 %0 : java.type:"java.lang.Object" = constant @null;
90 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
91 %2 : java.type:"java.lang.Object" = constant @null;
92 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
93 %4 : java.type:"DenotableTypesTest$A" = invoke %1 %3 @java.ref:"DenotableTypesTest::pick(java.lang.Object, java.lang.Object):java.lang.Object";
94 return;
95 };
96 """)
97 static void test4() { // @@@ cast?
98 pick((C)null, (D)null);
99 }
100
101 @Reflect
102 @IR("""
103 func @"test5" ()java.type:"void" -> {
104 %0 : java.type:"java.util.List<? extends java.lang.Number>" = constant @null;
105 %1 : Var<java.type:"java.util.List<? extends java.lang.Number>"> = var %0 @"l";
106 %2 : java.type:"java.util.List<? extends java.lang.Number>" = var.load %1;
107 %3 : java.type:"int" = constant @0;
108 %4 : java.type:"java.lang.Number" = invoke %2 %3 @java.ref:"java.util.List::get(int):java.lang.Object";
109 return;
110 };
111 """)
112 static void test5() { // @@@ cast?
113 List<? extends Number> l = null;
114 l.get(0);
115 }
116
117 @Reflect
118 @IR("""
119 func @"test6" ()java.type:"void" -> {
120 %0 : java.type:"java.util.List<? super java.lang.Number>" = constant @null;
121 %1 : Var<java.type:"java.util.List<? super java.lang.Number>"> = var %0 @"l";
122 %2 : java.type:"java.util.List<? super java.lang.Number>" = var.load %1;
123 %3 : java.type:"int" = constant @0;
124 %4 : java.type:"java.lang.Object" = invoke %2 %3 @java.ref:"java.util.List::get(int):java.lang.Object";
125 return;
126 };
127 """)
128 static void test6() {
129 List<? super Number> l = null;
130 l.get(0);
131 }
132
133 static void consume(Runnable r) { }
134
135 @Reflect
136 @IR("""
137 func @"test7" ()java.type:"void" -> {
138 %0 : java.type:"&DenotableTypesTest::test7():void::<X>" = constant @null;
139 %1 : Var<java.type:"&DenotableTypesTest::test7():void::<X>"> = var %0 @"x";
140 %2 : java.type:"&DenotableTypesTest::test7():void::<X>" = var.load %1;
141 %3 : java.type:"java.lang.Runnable" = cast %2 @java.type:"java.lang.Runnable";
142 invoke %3 @java.ref:"DenotableTypesTest::consume(java.lang.Runnable):void";
143 return;
144 };
145 """)
146 static <X extends Object & Runnable> void test7() {
147 X x = null;
148 consume(x);
149 }
150
151 interface Adder<X> {
152 void add(Adder<X> adder);
153 }
154
155 @Reflect
156 @IR("""
157 func @"test8" (%0 : java.type:"java.util.List<? extends DenotableTypesTest$Adder<java.lang.Integer>>")java.type:"void" -> {
158 %1 : Var<java.type:"java.util.List<? extends DenotableTypesTest$Adder<java.lang.Integer>>"> = var %0 @"list";
159 %2 : java.type:"java.util.List<? extends DenotableTypesTest$Adder<java.lang.Integer>>" = var.load %1;
160 %3 : java.type:"int" = constant @0;
161 %4 : java.type:"DenotableTypesTest$Adder<java.lang.Integer>" = invoke %2 %3 @java.ref:"java.util.List::get(int):java.lang.Object";
162 %5 : java.type:"java.util.List<? extends DenotableTypesTest$Adder<java.lang.Integer>>" = var.load %1;
163 %6 : java.type:"int" = constant @1;
164 %7 : java.type:"DenotableTypesTest$Adder<java.lang.Integer>" = invoke %5 %6 @java.ref:"java.util.List::get(int):java.lang.Object";
165 invoke %4 %7 @java.ref:"DenotableTypesTest$Adder::add(DenotableTypesTest$Adder):void";
166 return;
167 };
168 """)
169 static void test8(List<? extends Adder<Integer>> list) {
170 list.get(0).add(list.get(1));
171 }
172
173 static class Box<X> {
174 X x;
175 }
176
177 @Reflect
178 @IR("""
179 func @"test9" (%0 : java.type:"java.util.List<? extends DenotableTypesTest$Box<java.lang.Integer>>")java.type:"void" -> {
180 %1 : Var<java.type:"java.util.List<? extends DenotableTypesTest$Box<java.lang.Integer>>"> = var %0 @"list";
181 %2 : java.type:"java.util.List<? extends DenotableTypesTest$Box<java.lang.Integer>>" = var.load %1;
182 %3 : java.type:"int" = constant @0;
183 %4 : java.type:"DenotableTypesTest$Box<java.lang.Integer>" = invoke %2 %3 @java.ref:"java.util.List::get(int):java.lang.Object";
184 %5 : java.type:"java.lang.Integer" = field.load %4 @java.ref:"DenotableTypesTest$Box::x:java.lang.Object";
185 %6 : Var<java.type:"java.lang.Integer"> = var %5 @"i";
186 return;
187 };
188 """)
189 static void test9(List<? extends Box<Integer>> list) {
190 Integer i = list.get(0).x;
191 }
192
193 interface E {
194 void m();
195 }
196
197 static class XA extends Exception implements E {
198 public void m() { }
199 }
200
201 static class XB extends Exception implements E {
202 public void m() { }
203 }
204
205 static void g() throws XA, XB { }
206
207 @Reflect
208 @IR("""
209 func @"test10" ()java.type:"void" -> {
210 java.try
211 ()java.type:"void" -> {
212 invoke @java.ref:"DenotableTypesTest::g():void";
213 yield;
214 }
215 (%0 : java.type:"java.lang.Exception")java.type:"void" -> {
216 %1 : Var<java.type:"java.lang.Exception"> = var %0 @"x";
217 %2 : java.type:"java.lang.Exception" = var.load %1;
218 %3 : java.type:"DenotableTypesTest$E" = cast %2 @java.type:"DenotableTypesTest$E";
219 invoke %3 @java.ref:"DenotableTypesTest$E::m():void";
220 yield;
221 };
222 return;
223 };
224 """)
225 static void test10() {
226 try {
227 g();
228 } catch (XA | XB x) {
229 x.m();
230 }
231 }
232
233 static <Z> List<Z> pickInv(Z z1, Z z2) { return null; }
234 static <Z> List<? extends Z> pickExt(Z z1, Z z2) { return null; }
235 static <Z> List<? super Z> pickSup(Z z1, Z z2) { return null; }
236
237 // test intersections
238
239 @Reflect
240 @IR("""
241 func @"test11" ()java.type:"void" -> {
242 %0 : java.type:"java.lang.Object" = constant @null;
243 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
244 %2 : java.type:"java.lang.Object" = constant @null;
245 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
246 %4 : java.type:"java.util.List<? extends DenotableTypesTest$A>" = invoke %1 %3 @java.ref:"DenotableTypesTest::pickInv(java.lang.Object, java.lang.Object):java.util.List";
247 return;
248 };
249 """)
250 static void test11() {
251 pickInv((C)null, (D)null);
252 }
253
254 @Reflect
255 @IR("""
256 func @"test12" ()java.type:"void" -> {
257 %0 : java.type:"java.lang.Object" = constant @null;
258 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
259 %2 : java.type:"java.lang.Object" = constant @null;
260 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
261 %4 : java.type:"java.util.List<? extends DenotableTypesTest$A>" = invoke %1 %3 @java.ref:"DenotableTypesTest::pickExt(java.lang.Object, java.lang.Object):java.util.List";
262 return;
263 };
264 """)
265 static void test12() {
266 pickExt((C)null, (D)null);
267 }
268
269 @Reflect
270 @IR("""
271 func @"test13" ()java.type:"void" -> {
272 %0 : java.type:"java.lang.Object" = constant @null;
273 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
274 %2 : java.type:"java.lang.Object" = constant @null;
275 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
276 %4 : java.type:"java.util.List<?>" = invoke %1 %3 @java.ref:"DenotableTypesTest::pickSup(java.lang.Object, java.lang.Object):java.util.List";
277 return;
278 };
279 """)
280 static void test13() {
281 pickSup((C)null, (D)null);
282 }
283
284 static <Z> List<Z[]> pickInvArr(Z z1, Z z2) { return null; }
285 static <Z> List<? extends Z[]> pickExtArr(Z z1, Z z2) { return null; }
286 static <Z> List<? super Z[]> pickSupArr(Z z1, Z z2) { return null; }
287
288 // test arrays of intersections
289
290 @Reflect
291 @IR("""
292 func @"test14" ()java.type:"void" -> {
293 %0 : java.type:"java.lang.Object" = constant @null;
294 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
295 %2 : java.type:"java.lang.Object" = constant @null;
296 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
297 %4 : java.type:"java.util.List<? extends DenotableTypesTest$A[]>" = invoke %1 %3 @java.ref:"DenotableTypesTest::pickInvArr(java.lang.Object, java.lang.Object):java.util.List";
298 return;
299 };
300 """)
301 static void test14() {
302 pickInvArr((C)null, (D)null);
303 }
304
305 @Reflect
306 @IR("""
307 func @"test15" ()java.type:"void" -> {
308 %0 : java.type:"java.lang.Object" = constant @null;
309 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
310 %2 : java.type:"java.lang.Object" = constant @null;
311 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
312 %4 : java.type:"java.util.List<? extends DenotableTypesTest$A[]>" = invoke %1 %3 @java.ref:"DenotableTypesTest::pickExtArr(java.lang.Object, java.lang.Object):java.util.List";
313 return;
314 };
315 """)
316 static void test15() {
317 pickExtArr((C)null, (D)null);
318 }
319
320 @Reflect
321 @IR("""
322 func @"test16" ()java.type:"void" -> {
323 %0 : java.type:"java.lang.Object" = constant @null;
324 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
325 %2 : java.type:"java.lang.Object" = constant @null;
326 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
327 %4 : java.type:"java.util.List<?>" = invoke %1 %3 @java.ref:"DenotableTypesTest::pickSupArr(java.lang.Object, java.lang.Object):java.util.List";
328 return;
329 };
330 """)
331 static void test16() {
332 pickSupArr((C)null, (D)null);
333 }
334
335 interface F<X> { }
336 interface G<X> { }
337 static class H<X> implements F<X>, G<X> { }
338 static class I<X> implements F<X>, G<X> { }
339
340 static <Z> H<Z> pickH(Z z1, Z z2) { return null; }
341 static <Z> I<Z> pickI(Z z1, Z z2) { return null; }
342
343 // test intersections of intersections
344
345 @Reflect
346 @IR("""
347 func @"test17" ()java.type:"void" -> {
348 %0 : java.type:"java.lang.Object" = constant @null;
349 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
350 %2 : java.type:"java.lang.Object" = constant @null;
351 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
352 %4 : java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>" = invoke %1 %3 @java.ref:"DenotableTypesTest::pickH(java.lang.Object, java.lang.Object):DenotableTypesTest$H";
353 %5 : Var<java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>"> = var %4 @"fst";
354 %6 : java.type:"java.lang.Object" = constant @null;
355 %7 : java.type:"DenotableTypesTest$C" = cast %6 @java.type:"DenotableTypesTest$C";
356 %8 : java.type:"java.lang.Object" = constant @null;
357 %9 : java.type:"DenotableTypesTest$D" = cast %8 @java.type:"DenotableTypesTest$D";
358 %10 : java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>" = invoke %7 %9 @java.ref:"DenotableTypesTest::pickI(java.lang.Object, java.lang.Object):DenotableTypesTest$I";
359 %11 : Var<java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>"> = var %10 @"snd";
360 %12 : java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>" = var.load %5;
361 %13 : java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>" = var.load %11;
362 %14 : java.type:"java.util.List<? extends DenotableTypesTest$F<? extends DenotableTypesTest$A>>" = invoke %12 %13 @java.ref:"DenotableTypesTest::pickInv(java.lang.Object, java.lang.Object):java.util.List";
363 return;
364 };
365 """)
366 static void test17() {
367 var fst = pickH((C)null, (D)null);
368 var snd = pickI((C)null, (D)null);
369 pickInv(fst, snd);
370 }
371
372 @Reflect
373 @IR("""
374 func @"test18" ()java.type:"void" -> {
375 %0 : java.type:"java.lang.Object" = constant @null;
376 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
377 %2 : java.type:"java.lang.Object" = constant @null;
378 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
379 %4 : java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>" = invoke %1 %3 @java.ref:"DenotableTypesTest::pickH(java.lang.Object, java.lang.Object):DenotableTypesTest$H";
380 %5 : Var<java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>"> = var %4 @"fst";
381 %6 : java.type:"java.lang.Object" = constant @null;
382 %7 : java.type:"DenotableTypesTest$C" = cast %6 @java.type:"DenotableTypesTest$C";
383 %8 : java.type:"java.lang.Object" = constant @null;
384 %9 : java.type:"DenotableTypesTest$D" = cast %8 @java.type:"DenotableTypesTest$D";
385 %10 : java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>" = invoke %7 %9 @java.ref:"DenotableTypesTest::pickI(java.lang.Object, java.lang.Object):DenotableTypesTest$I";
386 %11 : Var<java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>"> = var %10 @"snd";
387 %12 : java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>" = var.load %5;
388 %13 : java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>" = var.load %11;
389 %14 : java.type:"java.util.List<? extends DenotableTypesTest$F<? extends DenotableTypesTest$A>>" = invoke %12 %13 @java.ref:"DenotableTypesTest::pickExt(java.lang.Object, java.lang.Object):java.util.List";
390 return;
391 };
392 """)
393 static void test18() {
394 var fst = pickH((C)null, (D)null);
395 var snd = pickI((C)null, (D)null);
396 pickExt(fst, snd);
397 }
398
399 @Reflect
400 @IR("""
401 func @"test19" ()java.type:"void" -> {
402 %0 : java.type:"java.lang.Object" = constant @null;
403 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
404 %2 : java.type:"java.lang.Object" = constant @null;
405 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
406 %4 : java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>" = invoke %1 %3 @java.ref:"DenotableTypesTest::pickH(java.lang.Object, java.lang.Object):DenotableTypesTest$H";
407 %5 : Var<java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>"> = var %4 @"fst";
408 %6 : java.type:"java.lang.Object" = constant @null;
409 %7 : java.type:"DenotableTypesTest$C" = cast %6 @java.type:"DenotableTypesTest$C";
410 %8 : java.type:"java.lang.Object" = constant @null;
411 %9 : java.type:"DenotableTypesTest$D" = cast %8 @java.type:"DenotableTypesTest$D";
412 %10 : java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>" = invoke %7 %9 @java.ref:"DenotableTypesTest::pickI(java.lang.Object, java.lang.Object):DenotableTypesTest$I";
413 %11 : Var<java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>"> = var %10 @"snd";
414 %12 : java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>" = var.load %5;
415 %13 : java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>" = var.load %11;
416 %14 : java.type:"java.util.List<?>" = invoke %12 %13 @java.ref:"DenotableTypesTest::pickSup(java.lang.Object, java.lang.Object):java.util.List";
417 return;
418 };
419 """)
420 static void test19() {
421 var fst = pickH((C)null, (D)null);
422 var snd = pickI((C)null, (D)null);
423 pickSup(fst, snd);
424 }
425 }