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