1 /*
2 * Copyright (c) 2024, 2025, 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:"DenotableTypesTest$Adder<java.lang.Integer>" = cast %4 @java.type:"DenotableTypesTest$Adder";
163 %6 : java.type:"java.util.List<? extends DenotableTypesTest$Adder<java.lang.Integer>>" = var.load %1;
164 %7 : java.type:"int" = constant @1;
165 %8 : java.type:"DenotableTypesTest$Adder<java.lang.Integer>" = invoke %6 %7 @java.ref:"java.util.List::get(int):java.lang.Object";
166 %9 : java.type:"DenotableTypesTest$Adder<java.lang.Integer>" = cast %8 @java.type:"DenotableTypesTest$Adder";
167 invoke %5 %9 @java.ref:"DenotableTypesTest$Adder::add(DenotableTypesTest$Adder):void";
168 return;
169 };
170 """)
171 static void test8(List<? extends Adder<Integer>> list) {
172 list.get(0).add(list.get(1));
173 }
174
175 static class Box<X> {
176 X x;
177 }
178
179 @Reflect
180 @IR("""
181 func @"test9" (%0 : java.type:"java.util.List<? extends DenotableTypesTest$Box<java.lang.Integer>>")java.type:"void" -> {
182 %1 : Var<java.type:"java.util.List<? extends DenotableTypesTest$Box<java.lang.Integer>>"> = var %0 @"list";
183 %2 : java.type:"java.util.List<? extends DenotableTypesTest$Box<java.lang.Integer>>" = var.load %1;
184 %3 : java.type:"int" = constant @0;
185 %4 : java.type:"DenotableTypesTest$Box<java.lang.Integer>" = invoke %2 %3 @java.ref:"java.util.List::get(int):java.lang.Object";
186 %5 : java.type:"DenotableTypesTest$Box<java.lang.Integer>" = cast %4 @java.type:"DenotableTypesTest$Box";
187 %6 : java.type:"java.lang.Integer" = field.load %5 @java.ref:"DenotableTypesTest$Box::x:java.lang.Object";
188 %7 : java.type:"java.lang.Integer" = cast %6 @java.type:"java.lang.Integer";
189 %8 : Var<java.type:"java.lang.Integer"> = var %7 @"i";
190 return;
191 };
192 """)
193 static void test9(List<? extends Box<Integer>> list) {
194 Integer i = list.get(0).x;
195 }
196
197 interface E {
198 void m();
199 }
200
201 static class XA extends Exception implements E {
202 public void m() { }
203 }
204
205 static class XB extends Exception implements E {
206 public void m() { }
207 }
208
209 static void g() throws XA, XB { }
210
211 @Reflect
212 @IR("""
213 func @"test10" ()java.type:"void" -> {
214 java.try @Tuple<Tuple<java.type:"DenotableTypesTest$XA", java.type:"DenotableTypesTest$XB">>
215 ()java.type:"void" -> {
216 invoke @java.ref:"DenotableTypesTest::g():void";
217 yield;
218 }
219 (%0 : java.type:"java.lang.Exception")java.type:"void" -> {
220 %1 : Var<java.type:"java.lang.Exception"> = var %0 @"x";
221 %2 : java.type:"java.lang.Exception" = var.load %1;
222 %3 : java.type:"DenotableTypesTest$E" = cast %2 @java.type:"DenotableTypesTest$E";
223 invoke %3 @java.ref:"DenotableTypesTest$E::m():void";
224 yield;
225 };
226 return;
227 };
228 """)
229 static void test10() {
230 try {
231 g();
232 } catch (XA | XB x) {
233 x.m();
234 }
235 }
236
237 static <Z> List<Z> pickInv(Z z1, Z z2) { return null; }
238 static <Z> List<? extends Z> pickExt(Z z1, Z z2) { return null; }
239 static <Z> List<? super Z> pickSup(Z z1, Z z2) { return null; }
240
241 // test intersections
242
243 @Reflect
244 @IR("""
245 func @"test11" ()java.type:"void" -> {
246 %0 : java.type:"java.lang.Object" = constant @null;
247 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
248 %2 : java.type:"java.lang.Object" = constant @null;
249 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
250 %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";
251 return;
252 };
253 """)
254 static void test11() {
255 pickInv((C)null, (D)null);
256 }
257
258 @Reflect
259 @IR("""
260 func @"test12" ()java.type:"void" -> {
261 %0 : java.type:"java.lang.Object" = constant @null;
262 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
263 %2 : java.type:"java.lang.Object" = constant @null;
264 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
265 %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";
266 return;
267 };
268 """)
269 static void test12() {
270 pickExt((C)null, (D)null);
271 }
272
273 @Reflect
274 @IR("""
275 func @"test13" ()java.type:"void" -> {
276 %0 : java.type:"java.lang.Object" = constant @null;
277 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
278 %2 : java.type:"java.lang.Object" = constant @null;
279 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
280 %4 : java.type:"java.util.List<?>" = invoke %1 %3 @java.ref:"DenotableTypesTest::pickSup(java.lang.Object, java.lang.Object):java.util.List";
281 return;
282 };
283 """)
284 static void test13() {
285 pickSup((C)null, (D)null);
286 }
287
288 static <Z> List<Z[]> pickInvArr(Z z1, Z z2) { return null; }
289 static <Z> List<? extends Z[]> pickExtArr(Z z1, Z z2) { return null; }
290 static <Z> List<? super Z[]> pickSupArr(Z z1, Z z2) { return null; }
291
292 // test arrays of intersections
293
294 @Reflect
295 @IR("""
296 func @"test14" ()java.type:"void" -> {
297 %0 : java.type:"java.lang.Object" = constant @null;
298 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
299 %2 : java.type:"java.lang.Object" = constant @null;
300 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
301 %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";
302 return;
303 };
304 """)
305 static void test14() {
306 pickInvArr((C)null, (D)null);
307 }
308
309 @Reflect
310 @IR("""
311 func @"test15" ()java.type:"void" -> {
312 %0 : java.type:"java.lang.Object" = constant @null;
313 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
314 %2 : java.type:"java.lang.Object" = constant @null;
315 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
316 %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";
317 return;
318 };
319 """)
320 static void test15() {
321 pickExtArr((C)null, (D)null);
322 }
323
324 @Reflect
325 @IR("""
326 func @"test16" ()java.type:"void" -> {
327 %0 : java.type:"java.lang.Object" = constant @null;
328 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
329 %2 : java.type:"java.lang.Object" = constant @null;
330 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
331 %4 : java.type:"java.util.List<?>" = invoke %1 %3 @java.ref:"DenotableTypesTest::pickSupArr(java.lang.Object, java.lang.Object):java.util.List";
332 return;
333 };
334 """)
335 static void test16() {
336 pickSupArr((C)null, (D)null);
337 }
338
339 interface F<X> { }
340 interface G<X> { }
341 static class H<X> implements F<X>, G<X> { }
342 static class I<X> implements F<X>, G<X> { }
343
344 static <Z> H<Z> pickH(Z z1, Z z2) { return null; }
345 static <Z> I<Z> pickI(Z z1, Z z2) { return null; }
346
347 // test intersections of intersections
348
349 @Reflect
350 @IR("""
351 func @"test17" ()java.type:"void" -> {
352 %0 : java.type:"java.lang.Object" = constant @null;
353 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
354 %2 : java.type:"java.lang.Object" = constant @null;
355 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
356 %4 : java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>" = invoke %1 %3 @java.ref:"DenotableTypesTest::pickH(java.lang.Object, java.lang.Object):DenotableTypesTest$H";
357 %5 : Var<java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>"> = var %4 @"fst";
358 %6 : java.type:"java.lang.Object" = constant @null;
359 %7 : java.type:"DenotableTypesTest$C" = cast %6 @java.type:"DenotableTypesTest$C";
360 %8 : java.type:"java.lang.Object" = constant @null;
361 %9 : java.type:"DenotableTypesTest$D" = cast %8 @java.type:"DenotableTypesTest$D";
362 %10 : java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>" = invoke %7 %9 @java.ref:"DenotableTypesTest::pickI(java.lang.Object, java.lang.Object):DenotableTypesTest$I";
363 %11 : Var<java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>"> = var %10 @"snd";
364 %12 : java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>" = var.load %5;
365 %13 : java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>" = var.load %11;
366 %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";
367 return;
368 };
369 """)
370 static void test17() {
371 var fst = pickH((C)null, (D)null);
372 var snd = pickI((C)null, (D)null);
373 pickInv(fst, snd);
374 }
375
376 @Reflect
377 @IR("""
378 func @"test18" ()java.type:"void" -> {
379 %0 : java.type:"java.lang.Object" = constant @null;
380 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
381 %2 : java.type:"java.lang.Object" = constant @null;
382 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
383 %4 : java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>" = invoke %1 %3 @java.ref:"DenotableTypesTest::pickH(java.lang.Object, java.lang.Object):DenotableTypesTest$H";
384 %5 : Var<java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>"> = var %4 @"fst";
385 %6 : java.type:"java.lang.Object" = constant @null;
386 %7 : java.type:"DenotableTypesTest$C" = cast %6 @java.type:"DenotableTypesTest$C";
387 %8 : java.type:"java.lang.Object" = constant @null;
388 %9 : java.type:"DenotableTypesTest$D" = cast %8 @java.type:"DenotableTypesTest$D";
389 %10 : java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>" = invoke %7 %9 @java.ref:"DenotableTypesTest::pickI(java.lang.Object, java.lang.Object):DenotableTypesTest$I";
390 %11 : Var<java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>"> = var %10 @"snd";
391 %12 : java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>" = var.load %5;
392 %13 : java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>" = var.load %11;
393 %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";
394 return;
395 };
396 """)
397 static void test18() {
398 var fst = pickH((C)null, (D)null);
399 var snd = pickI((C)null, (D)null);
400 pickExt(fst, snd);
401 }
402
403 @Reflect
404 @IR("""
405 func @"test19" ()java.type:"void" -> {
406 %0 : java.type:"java.lang.Object" = constant @null;
407 %1 : java.type:"DenotableTypesTest$C" = cast %0 @java.type:"DenotableTypesTest$C";
408 %2 : java.type:"java.lang.Object" = constant @null;
409 %3 : java.type:"DenotableTypesTest$D" = cast %2 @java.type:"DenotableTypesTest$D";
410 %4 : java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>" = invoke %1 %3 @java.ref:"DenotableTypesTest::pickH(java.lang.Object, java.lang.Object):DenotableTypesTest$H";
411 %5 : Var<java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>"> = var %4 @"fst";
412 %6 : java.type:"java.lang.Object" = constant @null;
413 %7 : java.type:"DenotableTypesTest$C" = cast %6 @java.type:"DenotableTypesTest$C";
414 %8 : java.type:"java.lang.Object" = constant @null;
415 %9 : java.type:"DenotableTypesTest$D" = cast %8 @java.type:"DenotableTypesTest$D";
416 %10 : java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>" = invoke %7 %9 @java.ref:"DenotableTypesTest::pickI(java.lang.Object, java.lang.Object):DenotableTypesTest$I";
417 %11 : Var<java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>"> = var %10 @"snd";
418 %12 : java.type:"DenotableTypesTest$H<? extends DenotableTypesTest$A>" = var.load %5;
419 %13 : java.type:"DenotableTypesTest$I<? extends DenotableTypesTest$A>" = var.load %11;
420 %14 : java.type:"java.util.List<?>" = invoke %12 %13 @java.ref:"DenotableTypesTest::pickSup(java.lang.Object, java.lang.Object):java.util.List";
421 return;
422 };
423 """)
424 static void test19() {
425 var fst = pickH((C)null, (D)null);
426 var snd = pickI((C)null, (D)null);
427 pickSup(fst, snd);
428 }
429
430 @Reflect
431 @IR("""
432 func @"test20" (%0 : java.type:"DenotableTypesTest$Box<? extends java.lang.Number>")java.type:"java.lang.Number" -> {
433 %1 : Var<java.type:"DenotableTypesTest$Box<? extends java.lang.Number>"> = var %0 @"box";
434 %2 : java.type:"DenotableTypesTest$Box<? extends java.lang.Number>" = var.load %1;
435 %3 : java.type:"java.lang.Number" = field.load %2 @java.ref:"DenotableTypesTest$Box::x:java.lang.Object";
436 %4 : java.type:"java.lang.Number" = cast %3 @java.type:"java.lang.Number";
437 return %4;
438 };
439 """)
440 static Number test20(Box<? extends Number> box) {
441 return box.x;
442 }
443
444 @Reflect
445 @IR("""
446 func @"test21" (%0 : java.type:"DenotableTypesTest$Box<? super java.lang.Number>")java.type:"java.lang.Object" -> {
447 %1 : Var<java.type:"DenotableTypesTest$Box<? super java.lang.Number>"> = var %0 @"box";
448 %2 : java.type:"DenotableTypesTest$Box<? super java.lang.Number>" = var.load %1;
449 %3 : java.type:"java.lang.Object" = field.load %2 @java.ref:"DenotableTypesTest$Box::x:java.lang.Object";
450 return %3;
451 };
452 """)
453 static Object test21(Box<? super Number> box) {
454 return box.x;
455 }
456 }