|
| 1 | +// |
| 2 | +// Tests that the static accessor method for lambda bodies |
| 3 | +// (generated under -Ydelambdafy:method) are compatible with |
| 4 | +// Java 8's LambdaMetafactory. |
| 5 | +// |
| 6 | +import java.lang.invoke._ |
| 7 | + |
| 8 | +class C { |
| 9 | + def test1: Unit = { |
| 10 | + (x: String) => x.reverse |
| 11 | + } |
| 12 | + def test2: Unit = { |
| 13 | + val capture1 = "capture1" |
| 14 | + (x: String) => capture1 + " " + x.reverse |
| 15 | + } |
| 16 | + def test3: Unit = { |
| 17 | + (x: String) => C.this + " " + x.reverse |
| 18 | + } |
| 19 | +} |
| 20 | +trait T { |
| 21 | + def test4: Unit = { |
| 22 | + (x: String) => x.reverse |
| 23 | + } |
| 24 | +} |
| 25 | + |
| 26 | +// A functional interface. Function1 contains abstract methods that are filled in by mixin |
| 27 | +trait Function1ish[A, B] { |
| 28 | + def apply(a: A): B |
| 29 | +} |
| 30 | + |
| 31 | +object Test { |
| 32 | + def lambdaFactory[A, B](hostClass: Class[_], instantiatedParam: Class[A], instantiatedRet: Class[B], accessorName: String, |
| 33 | + capturedParams: Array[(Class[_], AnyRef)] = Array()) = { |
| 34 | + val caller = MethodHandles.lookup |
| 35 | + val methodType = MethodType.methodType(classOf[AnyRef], Array[Class[_]](classOf[AnyRef])) |
| 36 | + val instantiatedMethodType = MethodType.methodType(instantiatedRet, Array[Class[_]](instantiatedParam)) |
| 37 | + val (capturedParamTypes, captured) = capturedParams.unzip |
| 38 | + val targetMethodType = MethodType.methodType(instantiatedRet, capturedParamTypes :+ instantiatedParam) |
| 39 | + val invokedType = MethodType.methodType(classOf[Function1ish[_, _]], capturedParamTypes) |
| 40 | + val target = caller.findStatic(hostClass, accessorName, targetMethodType) |
| 41 | + val site = LambdaMetafactory.metafactory(caller, "apply", invokedType, methodType, target, instantiatedMethodType) |
| 42 | + site.getTarget.invokeWithArguments(captured: _*).asInstanceOf[Function1ish[A, B]] |
| 43 | + } |
| 44 | + def main(args: Array[String]) { |
| 45 | + println(lambdaFactory(classOf[C], classOf[String], classOf[String], "accessor$1").apply("abc")) |
| 46 | + println(lambdaFactory(classOf[C], classOf[String], classOf[String], "accessor$2", Array(classOf[String] -> "capture1")).apply("abc")) |
| 47 | + println(lambdaFactory(classOf[C], classOf[String], classOf[String], "accessor$3", Array(classOf[C] -> new C)).apply("abc")) |
| 48 | + println(lambdaFactory(Class.forName("T$class"), classOf[String], classOf[String], "accessor$4", Array(classOf[T] -> new T{})).apply("abc")) |
| 49 | + } |
| 50 | +} |
0 commit comments