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