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.CodeReflection;
 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     @CodeReflection
 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     @CodeReflection
 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:"java.lang.Object" = field.load @java.ref:"IntersectionTypeTest$B::f_B:java.lang.Object";
 83                 %7 : Var<java.type:"java.lang.Object"> = var %6 @"oB";
 84                 %8 : java.type:"&IntersectionTypeTest::test2(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)" = var.load %1;
 85                 %9 : java.type:"java.lang.Object" = field.load @java.ref:"IntersectionTypeTest$C::f_C:java.lang.Object";
 86                 %10 : Var<java.type:"java.lang.Object"> = var %9 @"oC";
 87                 return;
 88             };
 89             """)
 90     static <X extends A & B & C> void test2(X x) {
 91         Object oA = x.f_A;
 92         Object oB = x.f_B;
 93         Object oC = x.f_C;
 94     }
 95 
 96     @CodeReflection
 97     @IR("""
 98             func @"test3" (%0 : java.type:"&IntersectionTypeTest::test3(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)")java.type:"void" -> {
 99                 %1 : Var<java.type:"&IntersectionTypeTest::test3(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)"> = var %0 @"x";
100                 %2 : java.type:"&IntersectionTypeTest::test3(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)" = var.load %1;
101                 %3 : Var<java.type:"IntersectionTypeTest$A"> = var %2 @"rec$";
102                 %4 : java.type:"java.lang.Runnable" = lambda ()java.type:"void" -> {
103                     %5 : java.type:"IntersectionTypeTest$A" = var.load %3;
104                     invoke %5 @java.ref:"IntersectionTypeTest$A::m_A():void";
105                     return;
106                 };
107                 %6 : Var<java.type:"java.lang.Runnable"> = var %4 @"rA";
108                 %7 : java.type:"&IntersectionTypeTest::test3(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)" = var.load %1;
109                 %8 : java.type:"IntersectionTypeTest$B" = cast %7 @java.type:"IntersectionTypeTest$B";
110                 %9 : Var<java.type:"IntersectionTypeTest$B"> = var %8 @"rec$";
111                 %10 : java.type:"java.lang.Runnable" = lambda ()java.type:"void" -> {
112                     %11 : java.type:"IntersectionTypeTest$B" = var.load %9;
113                     invoke %11 @java.ref:"IntersectionTypeTest$B::m_B():void";
114                     return;
115                 };
116                 %12 : Var<java.type:"java.lang.Runnable"> = var %10 @"rB";
117                 %13 : java.type:"&IntersectionTypeTest::test3(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)" = var.load %1;
118                 %14 : java.type:"IntersectionTypeTest$C" = cast %13 @java.type:"IntersectionTypeTest$C";
119                 %15 : Var<java.type:"IntersectionTypeTest$C"> = var %14 @"rec$";
120                 %16 : java.type:"java.lang.Runnable" = lambda ()java.type:"void" -> {
121                     %17 : java.type:"IntersectionTypeTest$C" = var.load %15;
122                     invoke %17 @java.ref:"IntersectionTypeTest$C::m_C():void";
123                     return;
124                 };
125                 %18 : Var<java.type:"java.lang.Runnable"> = var %16 @"rC";
126                 return;
127             };
128             """)
129     static <X extends A & B & C> void test3(X x) {
130         Runnable rA = x::m_A;
131         Runnable rB = x::m_B;
132         Runnable rC = x::m_C;
133     }
134 
135     static void g_A(A a) { }
136     static void g_B(B a) { }
137     static void g_C(C a) { }
138 
139     @CodeReflection
140     @IR("""
141             func @"test4" (%0 : java.type:"&IntersectionTypeTest::test4(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)")java.type:"void" -> {
142                 %1 : Var<java.type:"&IntersectionTypeTest::test4(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)"> = var %0 @"x";
143                 %2 : java.type:"&IntersectionTypeTest::test4(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)" = var.load %1;
144                 invoke %2 @java.ref:"IntersectionTypeTest::g_A(IntersectionTypeTest$A):void";
145                 %3 : java.type:"&IntersectionTypeTest::test4(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)" = var.load %1;
146                 %4 : java.type:"IntersectionTypeTest$B" = cast %3 @java.type:"IntersectionTypeTest$B";
147                 invoke %4 @java.ref:"IntersectionTypeTest::g_B(IntersectionTypeTest$B):void";
148                 %5 : java.type:"&IntersectionTypeTest::test4(IntersectionTypeTest$A):void::<X extends IntersectionTypeTest$A>)" = var.load %1;
149                 %6 : java.type:"IntersectionTypeTest$C" = cast %5 @java.type:"IntersectionTypeTest$C";
150                 invoke %6 @java.ref:"IntersectionTypeTest::g_C(IntersectionTypeTest$C):void";
151                 return;
152             };
153             """)
154     static <X extends A & B & C> void test4(X x) {
155         g_A(x);
156         g_B(x);
157         g_C(x);
158     }
159 
160     static <X extends A & B & C> X makeIntersection(X x1, X x2) {
161         return null;
162     }
163 
164     static class E1 implements A, B, C {
165         @Override
166         public void m_A() { }
167         @Override
168         public void m_B() { }
169         @Override
170         public void m_C() { }
171     }
172 
173     static class E2 implements A, B, C {
174         @Override
175         public void m_A() { }
176         @Override
177         public void m_B() { }
178         @Override
179         public void m_C() { }
180     }
181 
182     @CodeReflection
183     @IR("""
184             func @"test5" (%0 : java.type:"IntersectionTypeTest$E1", %1 : java.type:"IntersectionTypeTest$E2")java.type:"void" -> {
185                 %2 : Var<java.type:"IntersectionTypeTest$E1"> = var %0 @"e1";
186                 %3 : Var<java.type:"IntersectionTypeTest$E2"> = var %1 @"e2";
187                 %4 : java.type:"IntersectionTypeTest$E1" = var.load %2;
188                 %5 : java.type:"IntersectionTypeTest$E2" = var.load %3;
189                 %6 : java.type:"IntersectionTypeTest$A" = invoke %4 %5 @java.ref:"IntersectionTypeTest::makeIntersection(IntersectionTypeTest$A, IntersectionTypeTest$A):IntersectionTypeTest$A";
190                 %7 : Var<java.type:"IntersectionTypeTest$A"> = var %6 @"x";
191                 %8 : java.type:"IntersectionTypeTest$A" = var.load %7;
192                 invoke %8 @java.ref:"IntersectionTypeTest$A::m_A():void";
193                 %9 : java.type:"IntersectionTypeTest$A" = var.load %7;
194                 %10 : java.type:"IntersectionTypeTest$B" = cast %9 @java.type:"IntersectionTypeTest$B";
195                 invoke %10 @java.ref:"IntersectionTypeTest$B::m_B():void";
196                 %11 : java.type:"IntersectionTypeTest$A" = var.load %7;
197                 %12 : java.type:"IntersectionTypeTest$C" = cast %11 @java.type:"IntersectionTypeTest$C";
198                 invoke %12 @java.ref:"IntersectionTypeTest$C::m_C():void";
199                 return;
200             };
201             """)
202     static void test5(E1 e1, E2 e2) {
203         var x = makeIntersection(e1, e2);
204         x.m_A();
205         x.m_B();
206         x.m_C();
207     }
208 
209     @CodeReflection
210     @IR("""
211             func @"test6" (%0 : java.type:"IntersectionTypeTest$E1", %1 : java.type:"IntersectionTypeTest$E2")java.type:"void" -> {
212                 %2 : Var<java.type:"IntersectionTypeTest$E1"> = var %0 @"e1";
213                 %3 : Var<java.type:"IntersectionTypeTest$E2"> = var %1 @"e2";
214                 %4 : java.type:"IntersectionTypeTest$E1" = var.load %2;
215                 %5 : java.type:"IntersectionTypeTest$E2" = var.load %3;
216                 %6 : java.type:"IntersectionTypeTest$A" = invoke %4 %5 @java.ref:"IntersectionTypeTest::makeIntersection(IntersectionTypeTest$A, IntersectionTypeTest$A):IntersectionTypeTest$A";
217                 %7 : Var<java.type:"IntersectionTypeTest$A"> = var %6 @"x";
218                 %8 : java.type:"IntersectionTypeTest$A" = var.load %7;
219                 %9 : java.type:"java.lang.Object" = field.load @java.ref:"IntersectionTypeTest$A::f_A:java.lang.Object";
220                 %10 : Var<java.type:"java.lang.Object"> = var %9 @"oA";
221                 %11 : java.type:"IntersectionTypeTest$A" = var.load %7;
222                 %12 : java.type:"java.lang.Object" = field.load @java.ref:"IntersectionTypeTest$B::f_B:java.lang.Object";
223                 %13 : Var<java.type:"java.lang.Object"> = var %12 @"oB";
224                 %14 : java.type:"IntersectionTypeTest$A" = var.load %7;
225                 %15 : java.type:"java.lang.Object" = field.load @java.ref:"IntersectionTypeTest$C::f_C:java.lang.Object";
226                 %16 : Var<java.type:"java.lang.Object"> = var %15 @"oC";
227                 return;
228             };
229             """)
230     static void test6(E1 e1, E2 e2) {
231         var x = makeIntersection(e1, e2);
232         Object oA = x.f_A;
233         Object oB = x.f_B;
234         Object oC = x.f_C;
235     }
236 
237     @CodeReflection
238     @IR("""
239             func @"test7" (%0 : java.type:"IntersectionTypeTest$E1", %1 : java.type:"IntersectionTypeTest$E2")java.type:"void" -> {
240                 %2 : Var<java.type:"IntersectionTypeTest$E1"> = var %0 @"e1";
241                 %3 : Var<java.type:"IntersectionTypeTest$E2"> = var %1 @"e2";
242                 %4 : java.type:"IntersectionTypeTest$E1" = var.load %2;
243                 %5 : java.type:"IntersectionTypeTest$E2" = var.load %3;
244                 %6 : java.type:"IntersectionTypeTest$A" = invoke %4 %5 @java.ref:"IntersectionTypeTest::makeIntersection(IntersectionTypeTest$A, IntersectionTypeTest$A):IntersectionTypeTest$A";
245                 %7 : Var<java.type:"IntersectionTypeTest$A"> = var %6 @"x";
246                 %8 : java.type:"IntersectionTypeTest$A" = var.load %7;
247                 %9 : Var<java.type:"IntersectionTypeTest$A"> = var %8 @"rec$";
248                 %10 : java.type:"java.lang.Runnable" = lambda ()java.type:"void" -> {
249                     %11 : java.type:"IntersectionTypeTest$A" = var.load %9;
250                     invoke %11 @java.ref:"IntersectionTypeTest$A::m_A():void";
251                     return;
252                 };
253                 %12 : Var<java.type:"java.lang.Runnable"> = var %10 @"rA";
254                 %13 : java.type:"IntersectionTypeTest$A" = var.load %7;
255                 %14 : java.type:"IntersectionTypeTest$B" = cast %13 @java.type:"IntersectionTypeTest$B";
256                 %15 : Var<java.type:"IntersectionTypeTest$B"> = var %14 @"rec$";
257                 %16 : java.type:"java.lang.Runnable" = lambda ()java.type:"void" -> {
258                     %17 : java.type:"IntersectionTypeTest$B" = var.load %15;
259                     invoke %17 @java.ref:"IntersectionTypeTest$B::m_B():void";
260                     return;
261                 };
262                 %18 : Var<java.type:"java.lang.Runnable"> = var %16 @"rB";
263                 %19 : java.type:"IntersectionTypeTest$A" = var.load %7;
264                 %20 : java.type:"IntersectionTypeTest$C" = cast %19 @java.type:"IntersectionTypeTest$C";
265                 %21 : Var<java.type:"IntersectionTypeTest$C"> = var %20 @"rec$";
266                 %22 : java.type:"java.lang.Runnable" = lambda ()java.type:"void" -> {
267                     %23 : java.type:"IntersectionTypeTest$C" = var.load %21;
268                     invoke %23 @java.ref:"IntersectionTypeTest$C::m_C():void";
269                     return;
270                 };
271                 %24 : Var<java.type:"java.lang.Runnable"> = var %22 @"rC";
272                 return;
273             };
274             """)
275     static void test7(E1 e1, E2 e2) {
276         var x = makeIntersection(e1, e2);
277         Runnable rA = x::m_A;
278         Runnable rB = x::m_B;
279         Runnable rC = x::m_C;
280     }
281 
282     @CodeReflection
283     @IR("""
284             func @"test8" (%0 : java.type:"IntersectionTypeTest$E1", %1 : java.type:"IntersectionTypeTest$E2")java.type:"void" -> {
285                 %2 : Var<java.type:"IntersectionTypeTest$E1"> = var %0 @"e1";
286                 %3 : Var<java.type:"IntersectionTypeTest$E2"> = var %1 @"e2";
287                 %4 : java.type:"IntersectionTypeTest$E1" = var.load %2;
288                 %5 : java.type:"IntersectionTypeTest$E2" = var.load %3;
289                 %6 : java.type:"IntersectionTypeTest$A" = invoke %4 %5 @java.ref:"IntersectionTypeTest::makeIntersection(IntersectionTypeTest$A, IntersectionTypeTest$A):IntersectionTypeTest$A";
290                 %7 : Var<java.type:"IntersectionTypeTest$A"> = var %6 @"x";
291                 %8 : java.type:"IntersectionTypeTest$A" = var.load %7;
292                 invoke %8 @java.ref:"IntersectionTypeTest::g_A(IntersectionTypeTest$A):void";
293                 %9 : java.type:"IntersectionTypeTest$A" = var.load %7;
294                 %10 : java.type:"IntersectionTypeTest$B" = cast %9 @java.type:"IntersectionTypeTest$B";
295                 invoke %10 @java.ref:"IntersectionTypeTest::g_B(IntersectionTypeTest$B):void";
296                 %11 : java.type:"IntersectionTypeTest$A" = var.load %7;
297                 %12 : java.type:"IntersectionTypeTest$C" = cast %11 @java.type:"IntersectionTypeTest$C";
298                 invoke %12 @java.ref:"IntersectionTypeTest::g_C(IntersectionTypeTest$C):void";
299                 return;
300             };
301             """)
302     static void test8(E1 e1, E2 e2) {
303         var x = makeIntersection(e1, e2);
304         g_A(x);
305         g_B(x);
306         g_C(x);
307     }
308 }