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.Reflect;
 25 import java.util.function.BiConsumer;
 26 import java.util.function.Consumer;
 27 import java.util.function.Function;
 28 import java.util.function.IntFunction;
 29 import java.util.function.Supplier;
 30 
 31 /*
 32  * @test
 33  * @summary Smoke test for code reflection with method reference expressions.
 34  * @modules jdk.incubator.code
 35  * @compile MethodReferenceTest.java
 36  */
 37 
 38 public class MethodReferenceTest {
 39 
 40     static void m_s(String s) {}
 41 
 42     void m(String s) {}
 43 
 44     @Reflect
 45     @IR("""
 46             func @"test1" (%0 : java.type:"MethodReferenceTest")java.type:"void" -> {
 47                 %1 : java.type:"java.util.function.Consumer<java.lang.String>" = lambda @lambda.isQuotable=true (%2 : java.type:"java.lang.String")java.type:"void" -> {
 48                     %3 : Var<java.type:"java.lang.String"> = var %2 @"x$0";
 49                     %4 : java.type:"java.lang.String" = var.load %3;
 50                     invoke %4 @java.ref:"MethodReferenceTest::m_s(java.lang.String):void";
 51                     return;
 52                 };
 53                 %5 : Var<java.type:"java.util.function.Consumer<java.lang.String>"> = var %1 @"c";
 54                 return;
 55             };
 56             """)
 57     void test1() {
 58         Consumer<String> c = MethodReferenceTest::m_s;
 59     }
 60 
 61     @Reflect
 62     @IR("""
 63             func @"test2" (%0 : java.type:"MethodReferenceTest")java.type:"void" -> {
 64                 %1 : java.type:"java.util.function.BiConsumer<MethodReferenceTest, java.lang.String>" = lambda @lambda.isQuotable=true (%2 : java.type:"MethodReferenceTest", %3 : java.type:"java.lang.String")java.type:"void" -> {
 65                     %4 : Var<java.type:"MethodReferenceTest"> = var %2 @"rec$";
 66                     %5 : Var<java.type:"java.lang.String"> = var %3 @"x$0";
 67                     %6 : java.type:"MethodReferenceTest" = var.load %4;
 68                     %7 : java.type:"java.lang.String" = var.load %5;
 69                     invoke %6 %7 @java.ref:"MethodReferenceTest::m(java.lang.String):void";
 70                     return;
 71                 };
 72                 %8 : Var<java.type:"java.util.function.BiConsumer<MethodReferenceTest, java.lang.String>"> = var %1 @"bc";
 73                 return;
 74             };
 75             """)
 76     void test2() {
 77         BiConsumer<MethodReferenceTest, String> bc = MethodReferenceTest::m;
 78     }
 79 
 80     @Reflect
 81     @IR("""
 82             func @"test3" (%0 : java.type:"MethodReferenceTest")java.type:"void" -> {
 83                 %1 : java.type:"java.util.function.Consumer<java.lang.String>" = lambda @lambda.isQuotable=true (%2 : java.type:"java.lang.String")java.type:"void" -> {
 84                     %3 : Var<java.type:"java.lang.String"> = var %2 @"x$0";
 85                     %4 : java.type:"java.lang.String" = var.load %3;
 86                     invoke %0 %4 @java.ref:"MethodReferenceTest::m(java.lang.String):void";
 87                     return;
 88                 };
 89                 %5 : Var<java.type:"java.util.function.Consumer<java.lang.String>"> = var %1 @"c";
 90                 return;
 91             };
 92             """)
 93     void test3() {
 94         Consumer<String> c = this::m;
 95     }
 96 
 97     class A<T> {
 98         T m(T t) { return t; }
 99     }
100 
101     <T> A<T> a(T t) { return null; }
102 
103     @Reflect
104     @IR("""
105             func @"test4" (%0 : java.type:"MethodReferenceTest")java.type:"void" -> {
106                 %1 : java.type:"java.lang.String" = constant @"s";
107                 %2 : java.type:"MethodReferenceTest::A<java.lang.String>" = invoke %0 %1 @java.ref:"MethodReferenceTest::a(java.lang.Object):MethodReferenceTest::A";
108                 %3 : Var<java.type:"MethodReferenceTest::A<java.lang.String>"> = var %2 @"rec$";
109                 %4 : java.type:"java.util.function.Function<java.lang.String, java.lang.String>" = lambda @lambda.isQuotable=true (%5 : java.type:"java.lang.String")java.type:"java.lang.String" -> {
110                     %6 : Var<java.type:"java.lang.String"> = var %5 @"x$0";
111                     %7 : java.type:"MethodReferenceTest::A<java.lang.String>" = var.load %3;
112                     %8 : java.type:"java.lang.String" = var.load %6;
113                     %9 : java.type:"java.lang.String" = invoke %7 %8 @java.ref:"MethodReferenceTest::A::m(java.lang.Object):java.lang.Object";
114                     return %9;
115                 };
116                 %10 : Var<java.type:"java.util.function.Function<java.lang.String, java.lang.String>"> = var %4 @"f";
117                 return;
118             };
119             """)
120     void test4() {
121         Function<String, String> f = a("s")::m;
122     }
123 
124     @Reflect
125     @IR("""
126             func @"test5" (%0 : java.type:"MethodReferenceTest")java.type:"void" -> {
127                 %1 : java.type:"java.io.PrintStream" = field.load @java.ref:"java.lang.System::out:java.io.PrintStream";
128                 %2 : Var<java.type:"java.io.PrintStream"> = var %1 @"rec$";
129                 %3 : java.type:"java.util.function.Consumer<java.lang.String>" = lambda @lambda.isQuotable=true (%4 : java.type:"java.lang.String")java.type:"void" -> {
130                     %5 : Var<java.type:"java.lang.String"> = var %4 @"x$0";
131                     %6 : java.type:"java.io.PrintStream" = var.load %2;
132                     %7 : java.type:"java.lang.String" = var.load %5;
133                     invoke %6 %7 @java.ref:"java.io.PrintStream::println(java.lang.String):void";
134                     return;
135                 };
136                 %8 : Var<java.type:"java.util.function.Consumer<java.lang.String>"> = var %3 @"c3";
137                 return;
138             };
139             """)
140     void test5() {
141         Consumer<String> c3 = System.out::println;
142     }
143 
144     static class X {
145         X(int i) {}
146     }
147 
148     @Reflect
149     @IR("""
150             func @"test6" (%0 : java.type:"MethodReferenceTest")java.type:"void" -> {
151                 %1 : java.type:"java.util.function.Function<java.lang.Integer, MethodReferenceTest$X>" = lambda @lambda.isQuotable=true (%2 : java.type:"java.lang.Integer")java.type:"MethodReferenceTest$X" -> {
152                     %3 : Var<java.type:"java.lang.Integer"> = var %2 @"x$0";
153                     %4 : java.type:"java.lang.Integer" = var.load %3;
154                     %5 : java.type:"int" = invoke %4 @java.ref:"java.lang.Integer::intValue():int";
155                     %6 : java.type:"MethodReferenceTest$X" = new %5 @java.ref:"MethodReferenceTest$X::(int)";
156                     return %6;
157                 };
158                 %7 : Var<java.type:"java.util.function.Function<java.lang.Integer, MethodReferenceTest$X>"> = var %1 @"xNew";
159                 return;
160             };
161             """)
162     void test6() {
163         Function<Integer, X> xNew = X::new;
164     }
165 
166     @Reflect
167     @IR("""
168             func @"test7" (%0 : java.type:"MethodReferenceTest")java.type:"void" -> {
169                 %1 : java.type:"java.util.function.Supplier<MethodReferenceTest::A<java.lang.String>>" = lambda @lambda.isQuotable=true ()java.type:"MethodReferenceTest::A<java.lang.String>" -> {
170                     %2 : java.type:"MethodReferenceTest::A<java.lang.String>" = new %0 @java.ref:"MethodReferenceTest::A::(MethodReferenceTest)";
171                     return %2;
172                 };
173                 %3 : Var<java.type:"java.util.function.Supplier<MethodReferenceTest::A<java.lang.String>>"> = var %1 @"aNew";
174                 return;
175             };
176             """)
177     void test7() {
178         Supplier<A<String>> aNew = A::new;
179     }
180 
181     @Reflect
182     @IR("""
183             func @"test8" (%0 : java.type:"MethodReferenceTest")java.type:"void" -> {
184                 %1 : java.type:"java.util.function.IntFunction<MethodReferenceTest::A<java.lang.String>[]>" = lambda @lambda.isQuotable=true (%2 : java.type:"int")java.type:"MethodReferenceTest::A<java.lang.String>[]" -> {
185                     %3 : Var<java.type:"int"> = var %2 @"x$0";
186                     %4 : java.type:"int" = var.load %3;
187                     %5 : java.type:"MethodReferenceTest::A[]" = new %4 @java.ref:"MethodReferenceTest::A[]::(int)";
188                     return %5;
189                 };
190                 %6 : Var<java.type:"java.util.function.IntFunction<MethodReferenceTest::A<java.lang.String>[]>"> = var %1 @"aNewArray";
191                 return;
192             };
193             """)
194     void test8() {
195         IntFunction<A<String>[]> aNewArray = A[]::new;
196     }
197 
198 }