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 import java.util.function.Consumer;
26 import java.util.function.Function;
27 import java.util.function.IntSupplier;
28 import java.util.function.Predicate;
29 import java.util.function.Supplier;
30 import java.io.Serializable;
31
32 /*
33 * @test
34 * @summary Smoke test for code reflection with lambda expressions.
35 * @modules jdk.incubator.code
36 * @build LambdaTest
37 * @build CodeReflectionTester
38 * @run main CodeReflectionTester LambdaTest
39 */
40
41 public class LambdaTest {
42
43 @Reflect
44 @IR("""
45 func @"test1" (%0 : java.type:"LambdaTest")java.type:"void" -> {
46 %1 : java.type:"java.util.function.Consumer<java.lang.String>" = lambda @lambda.isReflectable=true (%2 : java.type:"java.lang.String")java.type:"void" -> {
47 %3 : Var<java.type:"java.lang.String"> = var %2 @"s";
48 %4 : java.type:"java.io.PrintStream" = field.load @java.ref:"java.lang.System::out:java.io.PrintStream";
49 %5 : java.type:"java.lang.String" = var.load %3;
50 invoke %4 %5 @java.ref:"java.io.PrintStream::println(java.lang.String):void";
51 return;
52 };
53 %6 : Var<java.type:"java.util.function.Consumer<java.lang.String>"> = var %1 @"c";
54 %7 : java.type:"java.util.function.Consumer<java.lang.String>" = var.load %6;
55 %8 : java.type:"java.lang.String" = constant @"Hello World";
56 invoke %7 %8 @java.ref:"java.util.function.Consumer::accept(java.lang.Object):void";
57 return;
58 };
59 """)
60 void test1() {
61 Consumer<String> c = s -> {
62 System.out.println(s);
63 };
64 c.accept("Hello World");
65 }
66
67 @Reflect
68 @IR("""
69 func @"test2" (%0 : java.type:"LambdaTest")java.type:"void" -> {
70 %1 : java.type:"java.util.function.Supplier<java.lang.String>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.String" -> {
71 %2 : java.type:"java.lang.String" = constant @"Hello World";
72 return %2;
73 };
74 %3 : Var<java.type:"java.util.function.Supplier<java.lang.String>"> = var %1 @"c";
75 %4 : java.type:"java.util.function.Supplier<java.lang.String>" = var.load %3;
76 %5 : java.type:"java.lang.String" = invoke %4 @java.ref:"java.util.function.Supplier::get():java.lang.Object";
77 %6 : Var<java.type:"java.lang.String"> = var %5 @"s";
78 return;
79 };
80 """)
81 void test2() {
82 Supplier<String> c = () -> {
83 return "Hello World";
84 };
85 String s = c.get();
86 }
87
88 @Reflect
89 @IR("""
90 func @"test3" (%0 : java.type:"LambdaTest")java.type:"void" -> {
91 %1 : java.type:"java.util.function.Supplier<java.lang.String>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.String" -> {
92 %2 : java.type:"java.lang.String" = constant @"Hello World";
93 return %2;
94 };
95 %3 : Var<java.type:"java.util.function.Supplier<java.lang.String>"> = var %1 @"c";
96 return;
97 };
98 """)
99 void test3() {
100 Supplier<String> c = () -> "Hello World";
101 }
102
103 String s_f;
104
105 @Reflect
106 @IR("""
107 func @"test4" (%0 : java.type:"LambdaTest")java.type:"void" -> {
108 %1 : java.type:"java.util.function.Supplier<java.lang.String>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.String" -> {
109 %2 : java.type:"java.lang.String" = field.load %0 @java.ref:"LambdaTest::s_f:java.lang.String";
110 return %2;
111 };
112 %3 : Var<java.type:"java.util.function.Supplier<java.lang.String>"> = var %1 @"c";
113 return;
114 };
115 """)
116 void test4() {
117 Supplier<String> c = () -> {
118 return s_f;
119 };
120 }
121
122 @Reflect
123 @IR("""
124 func @"test5" (%0 : java.type:"LambdaTest", %1 : java.type:"int", %2 : java.type:"int")java.type:"void" -> {
125 %3 : Var<java.type:"int"> = var %1 @"i";
126 %4 : Var<java.type:"int"> = var %2 @"j";
127 %5 : java.type:"int" = constant @3;
128 %6 : Var<java.type:"int"> = var %5 @"k";
129 %7 : java.type:"java.util.function.Supplier<java.lang.Integer>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Integer" -> {
130 %8 : java.type:"int" = constant @4;
131 %9 : Var<java.type:"int"> = var %8 @"l";
132 %10 : java.type:"java.util.function.Supplier<java.lang.Integer>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Integer" -> {
133 %11 : java.type:"int" = var.load %4;
134 %12 : java.type:"int" = var.load %6;
135 %13 : java.type:"int" = add %11 %12;
136 %14 : java.type:"int" = var.load %9;
137 %15 : java.type:"int" = add %13 %14;
138 %16 : Var<java.type:"int"> = var %15 @"r";
139 %17 : java.type:"int" = var.load %16;
140 %18 : java.type:"java.lang.Integer" = invoke %17 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
141 return %18;
142 };
143 %19 : Var<java.type:"java.util.function.Supplier<java.lang.Integer>"> = var %10 @"sInner";
144 %20 : java.type:"int" = var.load %3;
145 %21 : java.type:"java.util.function.Supplier<java.lang.Integer>" = var.load %19;
146 %22 : java.type:"java.lang.Integer" = invoke %21 @java.ref:"java.util.function.Supplier::get():java.lang.Object";
147 %23 : java.type:"int" = invoke %22 @java.ref:"java.lang.Integer::intValue():int";
148 %24 : java.type:"int" = add %20 %23;
149 %25 : Var<java.type:"int"> = var %24 @"r";
150 %26 : java.type:"int" = var.load %25;
151 %27 : java.type:"java.lang.Integer" = invoke %26 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
152 return %27;
153 };
154 %28 : Var<java.type:"java.util.function.Supplier<java.lang.Integer>"> = var %7 @"sOuter";
155 return;
156 };
157 """)
158 void test5(int i, int j) {
159 int k = 3;
160 Supplier<Integer> sOuter = () -> {
161 int l = 4;
162 Supplier<Integer> sInner = () -> {
163 int r = j + k + l;
164 return r;
165 };
166
167 int r = i + sInner.get();
168 return r;
169 };
170 }
171
172 int f;
173
174 @Reflect
175 @IR("""
176 func @"test6" (%0 : java.type:"LambdaTest")java.type:"void" -> {
177 %1 : java.type:"java.util.function.Supplier<java.lang.Integer>" = lambda @lambda.isReflectable=true ()java.type:"java.lang.Integer" -> {
178 %2 : java.type:"int" = field.load %0 @java.ref:"LambdaTest::f:int";
179 %3 : java.type:"java.lang.Integer" = invoke %2 @java.ref:"java.lang.Integer::valueOf(int):java.lang.Integer";
180 return %3;
181 };
182 %4 : Var<java.type:"java.util.function.Supplier<java.lang.Integer>"> = var %1 @"s";
183 return;
184 };
185 """)
186 void test6() {
187 Supplier<Integer> s = () -> f;
188 }
189
190 @Reflect
191 @IR("""
192 func @"test7" (%0 : java.type:"LambdaTest")java.type:"java.util.function.Predicate<java.lang.Object>" -> {
193 %1 : java.type:"java.util.function.Predicate<java.lang.Object>" = lambda @lambda.isReflectable=true (%2 : java.type:"java.lang.Object")java.type:"boolean" -> {
194 %3 : Var<java.type:"java.lang.Object"> = var %2 @"v";
195 %4 : Var<java.type:"java.lang.String"> = var @"s";
196 %5 : java.type:"boolean" = java.cand
197 ()java.type:"boolean" -> {
198 %6 : java.type:"java.lang.Object" = var.load %3;
199 %7 : java.type:"boolean" = pattern.match %6
200 ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" -> {
201 %8 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" = pattern.type @"s";
202 yield %8;
203 }
204 (%9 : java.type:"java.lang.String")java.type:"void" -> {
205 var.store %4 %9;
206 yield;
207 };
208 yield %7;
209 }
210 ()java.type:"boolean" -> {
211 %10 : java.type:"java.lang.String" = var.load %4;
212 %11 : java.type:"boolean" = invoke %10 @java.ref:"java.lang.String::isEmpty():boolean";
213 %12 : java.type:"boolean" = not %11;
214 yield %12;
215 };
216 return %5;
217 };
218 return %1;
219 };
220 """)
221 Predicate<Object> test7() {
222 return v -> v instanceof String s && !s.isEmpty();
223 }
224
225 @Reflect
226 @IR("""
227 func @"f" ()java.type:"void" -> {
228 %0 : java.type:"java.util.function.Predicate<java.lang.Object>" = lambda @lambda.isReflectable=true (%1 : java.type:"java.lang.Object")java.type:"boolean" -> {
229 %2 : Var<java.type:"java.lang.Object"> = var %1 @"v";
230 %3 : Var<java.type:"java.lang.String"> = var @"s";
231 %4 : java.type:"boolean" = java.cand
232 ()java.type:"boolean" -> {
233 %5 : java.type:"java.lang.Object" = var.load %2;
234 %6 : java.type:"boolean" = pattern.match %5
235 ()java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" -> {
236 %7 : java.type:"jdk.incubator.code.dialect.java.JavaOp$Pattern$Type<java.lang.String>" = pattern.type @"s";
237 yield %7;
238 }
239 (%8 : java.type:"java.lang.String")java.type:"void" -> {
240 var.store %3 %8;
241 yield;
242 };
243 yield %6;
244 }
245 ()java.type:"boolean" -> {
246 %9 : java.type:"java.lang.String" = var.load %3;
247 %10 : java.type:"boolean" = invoke %9 @java.ref:"java.lang.String::isEmpty():boolean";
248 %11 : java.type:"boolean" = not %10;
249 yield %11;
250 };
251 return %4;
252 };
253 return;
254 };
255 """)
256 static Predicate<Object> test8 = v -> v instanceof String s && !s.isEmpty();
257
258 @Reflect
259 @IR("""
260 func @"constantCapture" ()java.type:"java.util.function.IntSupplier" -> {
261 %0 : java.type:"int" = constant @1;
262 %1 : java.type:"int" = constant @2;
263 %2 : java.type:"int" = add %0 %1;
264 %3 : java.type:"java.util.function.IntSupplier" = lambda @lambda.isReflectable=true ()java.type:"int" -> {
265 return %2;
266 };
267 return %3;
268 };
269 """)
270 static IntSupplier constantCapture() {
271 final int i = 1 + 2;
272 return () -> i;
273 }
274
275 @Reflect
276 @IR("""
277 func @"constantAndRuntimeCapture" (%0 : java.type:"int")java.type:"java.util.function.IntSupplier" -> {
278 %1 : Var<java.type:"int"> = var %0 @"arg";
279 %2 : java.type:"int" = constant @1;
280 %3 : java.type:"int" = constant @2;
281 %4 : java.type:"int" = add %2 %3;
282 %5 : java.type:"java.util.function.IntSupplier" = lambda @lambda.isReflectable=true ()java.type:"int" -> {
283 %6 : java.type:"int" = var.load %1;
284 %7 : java.type:"int" = add %4 %6;
285 return %7;
286 };
287 return %5;
288 };
289 """)
290 static IntSupplier constantAndRuntimeCapture(int arg) {
291 final int i = 1 + 2;
292 return () -> i + arg;
293 }
294
295 @Reflect
296 @IR("""
297 func @"nestedCaptures" ()java.type:"java.util.function.Supplier<java.util.function.IntSupplier>" -> {
298 %0 : java.type:"int" = constant @1;
299 %1 : java.type:"int" = constant @2;
300 %2 : java.type:"int" = add %0 %1;
301 %3 : java.type:"java.util.function.Supplier<java.util.function.IntSupplier>" = lambda @lambda.isReflectable=true ()java.type:"java.util.function.IntSupplier" -> {
302 %4 : java.type:"int" = constant @4;
303 %5 : java.type:"int" = mul %2 %4;
304 %6 : java.type:"java.util.function.IntSupplier" = lambda @lambda.isReflectable=true ()java.type:"int" -> {
305 %7 : java.type:"int" = add %2 %5;
306 %8 : java.type:"int" = add %7 %2;
307 %9 : java.type:"int" = add %8 %5;
308 return %9;
309 };
310 return %6;
311 };
312 return %3;
313 };
314 """)
315 static Supplier<IntSupplier> nestedCaptures() {
316 final int methodConstant = 1 + 2;
317 return () -> {
318 final int outerConstant = methodConstant * 4;
319 return () -> {
320 final int innerConstant = methodConstant + outerConstant;
321 return innerConstant + methodConstant + outerConstant;
322 };
323 };
324 }
325
326 @Reflect
327 @IR("""
328 func @"intersectionTarget" ()java.type:"java.lang.String" -> {
329 %0 : java.type:"java.util.function.Function<java.lang.String, java.lang.String>" = lambda @lambda.isReflectable=true @lambda.additionalInterfaces=Tuple<java.type:"java.lang.Cloneable"> (%1 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
330 %2 : Var<java.type:"java.lang.String"> = var %1 @"x";
331 %3 : java.type:"java.lang.String" = var.load %2;
332 return %3;
333 };
334 %4 : java.type:"java.lang.Cloneable" = cast %0 @java.type:"java.lang.Cloneable";
335 %5 : Var<java.type:"java.util.function.Function<java.lang.String, java.lang.String>"> = var %4 @"f";
336 %6 : java.type:"java.util.function.Function<java.lang.String, java.lang.String>" = var.load %5;
337 %7 : java.type:"java.lang.String" = constant @"Hello World";
338 %8 : java.type:"java.lang.String" = invoke %6 %7 @java.ref:"java.util.function.Function::apply(java.lang.Object):java.lang.Object";
339 return %8;
340 };
341 """)
342 static String intersectionTarget() {
343 var f = (Function<String, String> & Cloneable) x -> x;
344 return f.apply("Hello World");
345 }
346 }