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 java.lang.runtime.CodeReflection;
 25 import java.util.List;
 26 
 27 /*
 28  * @test
 29  * @summary Smoke test for non-denotable types in IR type descriptors
 30  * @build DenotableTypesTest
 31  * @build CodeReflectionTester
 32  * @run main CodeReflectionTester DenotableTypesTest
 33  */
 34 
 35 public class DenotableTypesTest {
 36     static <X extends Number & Runnable> X m1(X x) { return null; }
 37     @CodeReflection
 38     @IR("""
 39             func @"test1" ()void -> {
 40                   %0 : java.lang.Number = constant @null;
 41                   %1 : java.lang.Number = invoke %0 @"DenotableTypesTest::m1(java.lang.Number)java.lang.Number";
 42                   return;
 43             };
 44             """)
 45     static void test1() {
 46         m1(null);
 47     }
 48 
 49     @CodeReflection
 50     @IR("""
 51             func @"test2" ()void -> {
 52                   %0 : int = constant @"1";
 53                   %1 : java.lang.Integer = invoke %0 @"java.lang.Integer::valueOf(int)java.lang.Integer";
 54                   %2 : double = constant @"3.0";
 55                   %3 : java.lang.Double = invoke %2 @"java.lang.Double::valueOf(double)java.lang.Double";
 56                   %4 : java.util.List<+<java.lang.Number>> = invoke %1 %3 @"java.util.List::of(java.lang.Object, java.lang.Object)java.util.List";
 57                   return;
 58             };
 59             """)
 60     static void test2() {
 61         List.of(1, 3d); // infinite type! (List<Object & Serializable & Comparable<...>>)
 62     }
 63 
 64     static <X extends Throwable> X m2(X x) throws X { return null; }
 65 
 66     @CodeReflection
 67     @IR("""
 68             func @"test3" ()void -> {
 69                 %0 : java.lang.RuntimeException = constant @null;
 70                 %1 : java.lang.RuntimeException = invoke %0 @"DenotableTypesTest::m2(java.lang.Throwable)java.lang.Throwable";
 71                 return;
 72             };
 73             """)
 74     static void test3() { // @@@ cast?
 75         m2(null);
 76     }
 77 
 78     interface A { }
 79     interface B { }
 80     static class C implements A, B { }
 81     static class D implements A, B { }
 82 
 83     static <Z> Z pick(Z z1, Z z2) { return null; }
 84 
 85     @CodeReflection
 86     @IR("""
 87             func @"test4" ()void -> {
 88                   %0 : java.lang.Object = constant @null;
 89                   %1 : DenotableTypesTest$C = cast %0 @"DenotableTypesTest$C";
 90                   %2 : java.lang.Object = constant @null;
 91                   %3 : DenotableTypesTest$D = cast %2 @"DenotableTypesTest$D";
 92                   %4 : DenotableTypesTest$A = invoke %1 %3 @"DenotableTypesTest::pick(java.lang.Object, java.lang.Object)java.lang.Object";
 93                   return;
 94             };
 95             """)
 96     static void test4() { // @@@ cast?
 97         pick((C)null, (D)null);
 98     }
 99 
100     @CodeReflection
101     @IR("""
102             func @"test5" ()void -> {
103                   %0 : java.util.List<+<java.lang.Number>> = constant @null;
104                   %1 : Var<java.util.List<+<java.lang.Number>>> = var %0 @"l";
105                   %2 : java.util.List<+<java.lang.Number>> = var.load %1;
106                   %3 : int = constant @"0";
107                   %4 : java.lang.Number = invoke %2 %3 @"java.util.List::get(int)java.lang.Object";
108                   return;
109             };
110             """)
111     static void test5() { // @@@ cast?
112         List<? extends Number> l = null;
113         l.get(0);
114     }
115 
116     @CodeReflection
117     @IR("""
118             func @"test6" ()void -> {
119                   %0 : java.util.List<-<java.lang.Number>> = constant @null;
120                   %1 : Var<java.util.List<-<java.lang.Number>>> = var %0 @"l";
121                   %2 : java.util.List<-<java.lang.Number>> = var.load %1;
122                   %3 : int = constant @"0";
123                   %4 : java.lang.Object = invoke %2 %3 @"java.util.List::get(int)java.lang.Object";
124                   return;
125             };
126             """)
127     static void test6() {
128         List<? super Number> l = null;
129         l.get(0);
130     }
131 
132     static void consume(Runnable r) { }
133 
134     @CodeReflection
135     @IR("""
136             func @"test7" ()void -> {
137                   %0 : #DenotableTypesTest::test7()void::X<java.lang.Object> = constant @null;
138                   %1 : Var<#DenotableTypesTest::test7()void::X<java.lang.Object>> = var %0 @"x";
139                   %2 : #DenotableTypesTest::test7()void::X<java.lang.Object> = var.load %1;
140                   %3 : java.lang.Runnable = cast %2 @"java.lang.Runnable";
141                   invoke %3 @"DenotableTypesTest::consume(java.lang.Runnable)void";
142                   return;
143             };
144             """)
145     static <X extends Object & Runnable> void test7() {
146         X x = null;
147         consume(x);
148     }
149 
150     interface Adder<X> {
151         void add(Adder<X> adder);
152     }
153 
154     @CodeReflection
155     @IR("""
156             func @"test8" (%0 : java.util.List<+<DenotableTypesTest$Adder<java.lang.Integer>>>)void -> {
157                   %1 : Var<java.util.List<+<DenotableTypesTest$Adder<java.lang.Integer>>>> = var %0 @"list";
158                   %2 : java.util.List<+<DenotableTypesTest$Adder<java.lang.Integer>>> = var.load %1;
159                   %3 : int = constant @"0";
160                   %4 : DenotableTypesTest$Adder<java.lang.Integer> = invoke %2 %3 @"java.util.List::get(int)java.lang.Object";
161                   %5 : java.util.List<+<DenotableTypesTest$Adder<java.lang.Integer>>> = var.load %1;
162                   %6 : int = constant @"1";
163                   %7 : DenotableTypesTest$Adder<java.lang.Integer> = invoke %5 %6 @"java.util.List::get(int)java.lang.Object";
164                   invoke %4 %7 @"DenotableTypesTest$Adder::add(DenotableTypesTest$Adder)void";
165                   return;
166             };
167             """)
168     static void test8(List<? extends Adder<Integer>> list) {
169         list.get(0).add(list.get(1));
170     }
171 
172     static class Box<X> {
173         X x;
174     }
175 
176     @CodeReflection
177     @IR("""
178             func @"test9" (%0 : java.util.List<+<DenotableTypesTest$Box<java.lang.Integer>>>)void -> {
179                   %1 : Var<java.util.List<+<DenotableTypesTest$Box<java.lang.Integer>>>> = var %0 @"list";
180                   %2 : java.util.List<+<DenotableTypesTest$Box<java.lang.Integer>>> = var.load %1;
181                   %3 : int = constant @"0";
182                   %4 : DenotableTypesTest$Box<java.lang.Integer> = invoke %2 %3 @"java.util.List::get(int)java.lang.Object";
183                   %5 : java.lang.Integer = field.load %4 @"DenotableTypesTest$Box::x()java.lang.Object";
184                   %6 : Var<java.lang.Integer> = var %5 @"i";
185                   return;
186             };
187             """)
188     static void test9(List<? extends Box<Integer>> list) {
189         Integer i = list.get(0).x;
190     }
191 
192     interface E {
193         void m();
194     }
195 
196     static class XA extends Exception implements E {
197         public void m() { }
198     }
199 
200     static class XB extends Exception implements E {
201         public void m() { }
202     }
203 
204     static void g() throws XA, XB { }
205 
206     @CodeReflection
207     @IR("""
208             func @"test10" ()void -> {
209                   java.try
210                       ()void -> {
211                           invoke @"DenotableTypesTest::g()void";
212                           yield;
213                       }
214                       (%0 : java.lang.Exception)void -> {
215                           %1 : Var<java.lang.Exception> = var %0 @"x";
216                           %2 : java.lang.Exception = var.load %1;
217                           %3 : DenotableTypesTest$E = cast %2 @"DenotableTypesTest$E";
218                           invoke %3 @"DenotableTypesTest$E::m()void";
219                           yield;
220                       };
221                   return;
222             };
223             """)
224     static void test10() {
225         try {
226             g();
227         } catch (XA | XB x) {
228             x.m();
229         }
230     }
231 }