1 /*
2 * Copyright (c) 2024, 2026, 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
26 /*
27 * @test
28 * @summary Smoke test for code reflection with intersection type conversions.
29 * @modules jdk.incubator.code
30 * @build IntersectionTypeTest
31 * @build CodeReflectionTester
32 * @run main CodeReflectionTester IntersectionTypeTest
33 */
34
35 class IntersectionTypeTest {
36 interface A {
37 Object f_A = 5;
38 void m_A();
39 }
40
41 interface B {
42 Object f_B = 5;
43 void m_B();
44 }
45
46 interface C {
47 Object f_C = 5;
48 void m_C();
49 }
50
51 @Reflect
52 @IR("""
53 func @"test1" (%0 : java.type:"&IntersectionTypeTest::test1(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)")java.type:"void" -> {
54 %1 : Var<java.type:"&IntersectionTypeTest::test1(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>"> = var %0 @"x";
55 %2 : java.type:"&IntersectionTypeTest::test1(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>" = var.load %1;
56 invoke %2 @java.ref:"IntersectionTypeTest$A::m_A():void";
57 %3 : java.type:"&IntersectionTypeTest::test1(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>" = var.load %1;
58 %4 : java.type:"IntersectionTypeTest$B" = cast %3 @java.type:"IntersectionTypeTest$B";
59 invoke %4 @java.ref:"IntersectionTypeTest$B::m_B():void";
60 %5 : java.type:"&IntersectionTypeTest::test1(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>" = var.load %1;
61 %6 : java.type:"IntersectionTypeTest$C" = cast %5 @java.type:"IntersectionTypeTest$C";
62 invoke %6 @java.ref:"IntersectionTypeTest$C::m_C():void";
63 return;
64 };
65 """)
66 static <X extends A & B & C> void test1(X x) {
67 x.m_A();
68 x.m_B();
69 x.m_C();
70 }
71
72 // #X<&m<IntersectionTypeTest, test2, func<void, IntersectionTypeTest$A>>, IntersectionTypeTest$A>
73 // #X<&m<IntersectionTypeTest, test2, func<void, IntersectionTypeTest$A>, IntersectionTypeTest$A>
74 @Reflect
75 @IR("""
76 func @"test2" (%0 : java.type:"&IntersectionTypeTest::test2(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>")java.type:"void" -> {
77 %1 : Var<java.type:"&IntersectionTypeTest::test2(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>"> = var %0 @"x";
78 %2 : java.type:"&IntersectionTypeTest::test2(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>" = var.load %1;
79 %3 : java.type:"java.lang.Object" = field.load @java.ref:"IntersectionTypeTest$A::f_A:java.lang.Object";
80 %4 : Var<java.type:"java.lang.Object"> = var %3 @"oA";
81 %5 : java.type:"&IntersectionTypeTest::test2(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>" = var.load %1;
82 %6 : java.type:"IntersectionTypeTest$B" = cast %5 @java.type:"IntersectionTypeTest$B";
83 %7 : java.type:"java.lang.Object" = field.load @java.ref:"IntersectionTypeTest$B::f_B:java.lang.Object";
84 %8 : Var<java.type:"java.lang.Object"> = var %7 @"oB";
85 %9 : java.type:"&IntersectionTypeTest::test2(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>" = var.load %1;
86 %10 : java.type:"IntersectionTypeTest$C" = cast %9 @java.type:"IntersectionTypeTest$C";
87 %11 : java.type:"java.lang.Object" = field.load @java.ref:"IntersectionTypeTest$C::f_C:java.lang.Object";
88 %12 : Var<java.type:"java.lang.Object"> = var %11 @"oC";
89 return;
90 };
91 """)
92 static <X extends A & B & C> void test2(X x) {
93 Object oA = x.f_A;
94 Object oB = x.f_B;
95 Object oC = x.f_C;
96 }
97
98 @Reflect
99 @IR("""
100 func @"test3" (%0 : java.type:"&IntersectionTypeTest::test3(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)")java.type:"void" -> {
101 %1 : Var<java.type:"&IntersectionTypeTest::test3(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)"> = var %0 @"x";
102 %2 : java.type:"&IntersectionTypeTest::test3(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)" = var.load %1;
103 %3 : Var<java.type:"IntersectionTypeTest$A"> = var %2 @"rec$";
104 %4 : java.type:"java.lang.Runnable" = lambda @lambda.isReflectable=true ()java.type:"void" -> {
105 %5 : java.type:"IntersectionTypeTest$A" = var.load %3;
106 invoke %5 @java.ref:"IntersectionTypeTest$A::m_A():void";
107 return;
108 };
109 %6 : Var<java.type:"java.lang.Runnable"> = var %4 @"rA";
110 %7 : java.type:"&IntersectionTypeTest::test3(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)" = var.load %1;
111 %8 : java.type:"IntersectionTypeTest$B" = cast %7 @java.type:"IntersectionTypeTest$B";
112 %9 : Var<java.type:"IntersectionTypeTest$B"> = var %8 @"rec$";
113 %10 : java.type:"java.lang.Runnable" = lambda @lambda.isReflectable=true ()java.type:"void" -> {
114 %11 : java.type:"IntersectionTypeTest$B" = var.load %9;
115 invoke %11 @java.ref:"IntersectionTypeTest$B::m_B():void";
116 return;
117 };
118 %12 : Var<java.type:"java.lang.Runnable"> = var %10 @"rB";
119 %13 : java.type:"&IntersectionTypeTest::test3(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)" = var.load %1;
120 %14 : java.type:"IntersectionTypeTest$C" = cast %13 @java.type:"IntersectionTypeTest$C";
121 %15 : Var<java.type:"IntersectionTypeTest$C"> = var %14 @"rec$";
122 %16 : java.type:"java.lang.Runnable" = lambda @lambda.isReflectable=true ()java.type:"void" -> {
123 %17 : java.type:"IntersectionTypeTest$C" = var.load %15;
124 invoke %17 @java.ref:"IntersectionTypeTest$C::m_C():void";
125 return;
126 };
127 %18 : Var<java.type:"java.lang.Runnable"> = var %16 @"rC";
128 return;
129 };
130 """)
131 static <X extends A & B & C> void test3(X x) {
132 Runnable rA = x::m_A;
133 Runnable rB = x::m_B;
134 Runnable rC = x::m_C;
135 }
136
137 static void g_A(A a) { }
138 static void g_B(B a) { }
139 static void g_C(C a) { }
140
141 @Reflect
142 @IR("""
143 func @"test4" (%0 : java.type:"&IntersectionTypeTest::test4(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)")java.type:"void" -> {
144 %1 : Var<java.type:"&IntersectionTypeTest::test4(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)"> = var %0 @"x";
145 %2 : java.type:"&IntersectionTypeTest::test4(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)" = var.load %1;
146 invoke %2 @java.ref:"IntersectionTypeTest::g_A(IntersectionTypeTest$A):void";
147 %3 : java.type:"&IntersectionTypeTest::test4(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)" = var.load %1;
148 %4 : java.type:"IntersectionTypeTest$B" = cast %3 @java.type:"IntersectionTypeTest$B";
149 invoke %4 @java.ref:"IntersectionTypeTest::g_B(IntersectionTypeTest$B):void";
150 %5 : java.type:"&IntersectionTypeTest::test4(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)" = var.load %1;
151 %6 : java.type:"IntersectionTypeTest$C" = cast %5 @java.type:"IntersectionTypeTest$C";
152 invoke %6 @java.ref:"IntersectionTypeTest::g_C(IntersectionTypeTest$C):void";
153 return;
154 };
155 """)
156 static <X extends A & B & C> void test4(X x) {
157 g_A(x);
158 g_B(x);
159 g_C(x);
160 }
161
162 static <X extends A & B & C> X makeIntersection(X x1, X x2) {
163 return null;
164 }
165
166 static class E1 implements A, B, C {
167 @Override
168 public void m_A() { }
169 @Override
170 public void m_B() { }
171 @Override
172 public void m_C() { }
173 }
174
175 static class E2 implements A, B, C {
176 @Override
177 public void m_A() { }
178 @Override
179 public void m_B() { }
180 @Override
181 public void m_C() { }
182 }
183
184 @Reflect
185 @IR("""
186 func @"test5" (%0 : java.type:"IntersectionTypeTest$E1", %1 : java.type:"IntersectionTypeTest$E2")java.type:"void" -> {
187 %2 : Var<java.type:"IntersectionTypeTest$E1"> = var %0 @"e1";
188 %3 : Var<java.type:"IntersectionTypeTest$E2"> = var %1 @"e2";
189 %4 : java.type:"IntersectionTypeTest$E1" = var.load %2;
190 %5 : java.type:"IntersectionTypeTest$E2" = var.load %3;
191 %6 : java.type:"IntersectionTypeTest$A" = invoke %4 %5 @java.ref:"IntersectionTypeTest::makeIntersection(IntersectionTypeTest$A, IntersectionTypeTest$A):IntersectionTypeTest$A";
192 %7 : Var<java.type:"IntersectionTypeTest$A"> = var %6 @"x";
193 %8 : java.type:"IntersectionTypeTest$A" = var.load %7;
194 invoke %8 @java.ref:"IntersectionTypeTest$A::m_A():void";
195 %9 : java.type:"IntersectionTypeTest$A" = var.load %7;
196 %10 : java.type:"IntersectionTypeTest$B" = cast %9 @java.type:"IntersectionTypeTest$B";
197 invoke %10 @java.ref:"IntersectionTypeTest$B::m_B():void";
198 %11 : java.type:"IntersectionTypeTest$A" = var.load %7;
199 %12 : java.type:"IntersectionTypeTest$C" = cast %11 @java.type:"IntersectionTypeTest$C";
200 invoke %12 @java.ref:"IntersectionTypeTest$C::m_C():void";
201 return;
202 };
203 """)
204 static void test5(E1 e1, E2 e2) {
205 var x = makeIntersection(e1, e2);
206 x.m_A();
207 x.m_B();
208 x.m_C();
209 }
210
211 @Reflect
212 @IR("""
213 func @"test6" (%0 : java.type:"IntersectionTypeTest$E1", %1 : java.type:"IntersectionTypeTest$E2")java.type:"void" -> {
214 %2 : Var<java.type:"IntersectionTypeTest$E1"> = var %0 @"e1";
215 %3 : Var<java.type:"IntersectionTypeTest$E2"> = var %1 @"e2";
216 %4 : java.type:"IntersectionTypeTest$E1" = var.load %2;
217 %5 : java.type:"IntersectionTypeTest$E2" = var.load %3;
218 %6 : java.type:"IntersectionTypeTest$A" = invoke %4 %5 @java.ref:"IntersectionTypeTest::makeIntersection(IntersectionTypeTest$A, IntersectionTypeTest$A):IntersectionTypeTest$A";
219 %7 : Var<java.type:"IntersectionTypeTest$A"> = var %6 @"x";
220 %8 : java.type:"IntersectionTypeTest$A" = var.load %7;
221 %9 : java.type:"java.lang.Object" = field.load @java.ref:"IntersectionTypeTest$A::f_A:java.lang.Object";
222 %10 : Var<java.type:"java.lang.Object"> = var %9 @"oA";
223 %11 : java.type:"IntersectionTypeTest$A" = var.load %7;
224 %12 : java.type:"IntersectionTypeTest$B" = cast %11 @java.type:"IntersectionTypeTest$B";
225 %13 : java.type:"java.lang.Object" = field.load @java.ref:"IntersectionTypeTest$B::f_B:java.lang.Object";
226 %14 : Var<java.type:"java.lang.Object"> = var %13 @"oB";
227 %15 : java.type:"IntersectionTypeTest$A" = var.load %7;
228 %16 : java.type:"IntersectionTypeTest$C" = cast %15 @java.type:"IntersectionTypeTest$C";
229 %17 : java.type:"java.lang.Object" = field.load @java.ref:"IntersectionTypeTest$C::f_C:java.lang.Object";
230 %18 : Var<java.type:"java.lang.Object"> = var %17 @"oC";
231 return;
232 };
233 """)
234 static void test6(E1 e1, E2 e2) {
235 var x = makeIntersection(e1, e2);
236 Object oA = x.f_A;
237 Object oB = x.f_B;
238 Object oC = x.f_C;
239 }
240
241 @Reflect
242 @IR("""
243 func @"test7" (%0 : java.type:"IntersectionTypeTest$E1", %1 : java.type:"IntersectionTypeTest$E2")java.type:"void" -> {
244 %2 : Var<java.type:"IntersectionTypeTest$E1"> = var %0 @"e1";
245 %3 : Var<java.type:"IntersectionTypeTest$E2"> = var %1 @"e2";
246 %4 : java.type:"IntersectionTypeTest$E1" = var.load %2;
247 %5 : java.type:"IntersectionTypeTest$E2" = var.load %3;
248 %6 : java.type:"IntersectionTypeTest$A" = invoke %4 %5 @java.ref:"IntersectionTypeTest::makeIntersection(IntersectionTypeTest$A, IntersectionTypeTest$A):IntersectionTypeTest$A";
249 %7 : Var<java.type:"IntersectionTypeTest$A"> = var %6 @"x";
250 %8 : java.type:"IntersectionTypeTest$A" = var.load %7;
251 %9 : Var<java.type:"IntersectionTypeTest$A"> = var %8 @"rec$";
252 %10 : java.type:"java.lang.Runnable" = lambda @lambda.isReflectable=true ()java.type:"void" -> {
253 %11 : java.type:"IntersectionTypeTest$A" = var.load %9;
254 invoke %11 @java.ref:"IntersectionTypeTest$A::m_A():void";
255 return;
256 };
257 %12 : Var<java.type:"java.lang.Runnable"> = var %10 @"rA";
258 %13 : java.type:"IntersectionTypeTest$A" = var.load %7;
259 %14 : java.type:"IntersectionTypeTest$B" = cast %13 @java.type:"IntersectionTypeTest$B";
260 %15 : Var<java.type:"IntersectionTypeTest$B"> = var %14 @"rec$";
261 %16 : java.type:"java.lang.Runnable" = lambda @lambda.isReflectable=true ()java.type:"void" -> {
262 %17 : java.type:"IntersectionTypeTest$B" = var.load %15;
263 invoke %17 @java.ref:"IntersectionTypeTest$B::m_B():void";
264 return;
265 };
266 %18 : Var<java.type:"java.lang.Runnable"> = var %16 @"rB";
267 %19 : java.type:"IntersectionTypeTest$A" = var.load %7;
268 %20 : java.type:"IntersectionTypeTest$C" = cast %19 @java.type:"IntersectionTypeTest$C";
269 %21 : Var<java.type:"IntersectionTypeTest$C"> = var %20 @"rec$";
270 %22 : java.type:"java.lang.Runnable" = lambda @lambda.isReflectable=true ()java.type:"void" -> {
271 %23 : java.type:"IntersectionTypeTest$C" = var.load %21;
272 invoke %23 @java.ref:"IntersectionTypeTest$C::m_C():void";
273 return;
274 };
275 %24 : Var<java.type:"java.lang.Runnable"> = var %22 @"rC";
276 return;
277 };
278 """)
279 static void test7(E1 e1, E2 e2) {
280 var x = makeIntersection(e1, e2);
281 Runnable rA = x::m_A;
282 Runnable rB = x::m_B;
283 Runnable rC = x::m_C;
284 }
285
286 @Reflect
287 @IR("""
288 func @"test8" (%0 : java.type:"IntersectionTypeTest$E1", %1 : java.type:"IntersectionTypeTest$E2")java.type:"void" -> {
289 %2 : Var<java.type:"IntersectionTypeTest$E1"> = var %0 @"e1";
290 %3 : Var<java.type:"IntersectionTypeTest$E2"> = var %1 @"e2";
291 %4 : java.type:"IntersectionTypeTest$E1" = var.load %2;
292 %5 : java.type:"IntersectionTypeTest$E2" = var.load %3;
293 %6 : java.type:"IntersectionTypeTest$A" = invoke %4 %5 @java.ref:"IntersectionTypeTest::makeIntersection(IntersectionTypeTest$A, IntersectionTypeTest$A):IntersectionTypeTest$A";
294 %7 : Var<java.type:"IntersectionTypeTest$A"> = var %6 @"x";
295 %8 : java.type:"IntersectionTypeTest$A" = var.load %7;
296 invoke %8 @java.ref:"IntersectionTypeTest::g_A(IntersectionTypeTest$A):void";
297 %9 : java.type:"IntersectionTypeTest$A" = var.load %7;
298 %10 : java.type:"IntersectionTypeTest$B" = cast %9 @java.type:"IntersectionTypeTest$B";
299 invoke %10 @java.ref:"IntersectionTypeTest::g_B(IntersectionTypeTest$B):void";
300 %11 : java.type:"IntersectionTypeTest$A" = var.load %7;
301 %12 : java.type:"IntersectionTypeTest$C" = cast %11 @java.type:"IntersectionTypeTest$C";
302 invoke %12 @java.ref:"IntersectionTypeTest::g_C(IntersectionTypeTest$C):void";
303 return;
304 };
305 """)
306 static void test8(E1 e1, E2 e2) {
307 var x = makeIntersection(e1, e2);
308 g_A(x);
309 g_B(x);
310 g_C(x);
311 }
312 }