Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ class JcInstListBuilder(val method: JcMethod,val instList: JcInstList<JcRawInst>

private fun tryResolveJcLambdaExpr(expr: JcRawDynamicCallExpr): JcLambdaExpr? {
if (expr.bsmArgs.size != 3) return null
val (interfaceMethodType, implementation, dynamicMethodType) = expr.bsmArgs
// RawInstListBuilder stores bootstrap arguments in reverse class-file order.
val (dynamicMethodType, implementation, interfaceMethodType) = expr.bsmArgs

if (interfaceMethodType !is BsmMethodTypeArg) return null
if (dynamicMethodType !is BsmMethodTypeArg) return null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,27 @@ class InvokeDynamicTest : BaseInstructionsTest() {
@Test
fun `invoke dynamic constructor`() = runStaticMethod<InvokeDynamicExamples>("testInvokeDynamicConstructor")

@Test
fun `erased and instantiated method types remain distinct for an unboxing reference`() {
assertLambdaMethodTypes(methodName = "makeWhitespacePredicate", implementationParameter = "int")
}

@Test
fun `instantiated method type retains the wrapper before implementation widening`() {
assertLambdaMethodTypes(methodName = "makeWideningPredicate", implementationParameter = "long")
}

private fun assertLambdaMethodTypes(methodName: String, implementationParameter: String) {
val clazz = cp.findClass<InvokeDynamicExamples>()
val method = clazz.declaredMethods.single { it.name == methodName }
val lambda = method.instList.filterIsInstance<JcAssignInst>()
.map { it.rhv }.filterIsInstance<JcLambdaExpr>().single()

assertEquals(listOf("java.lang.Object"), lambda.interfaceMethodType.argumentTypes.map { it.typeName })
assertEquals(listOf("java.lang.Integer"), lambda.dynamicMethodType.argumentTypes.map { it.typeName })
assertEquals(listOf(implementationParameter), lambda.actualMethod.method.parameters.map { it.type.typeName })
}

private inline fun <reified T> runStaticMethod(name: String) {
val clazz = cp.findClass<T>()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;

public class InvokeDynamicExamples {

Expand Down Expand Up @@ -161,4 +162,16 @@ public static String testNonStaticLambda() {
String actual = collection.innerMap.get("deadabc");
return expected.equals(actual) ? "OK" : "BAD";
}

public static Predicate<Integer> makeWhitespacePredicate() {
return Character::isWhitespace;
}

public static Predicate<Integer> makeWideningPredicate() {
return InvokeDynamicExamples::positiveLong;
}

private static boolean positiveLong(long value) {
return value > 0;
}
}
Loading