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