Do not generate generic signature for SAM wrapper methods

#KT-23870 Fixed
This commit is contained in:
Alexander Udalov
2018-07-19 20:37:29 +02:00
parent ac6874c221
commit 20ddbc9698
7 changed files with 132 additions and 9 deletions
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.config.JvmDefaultMode;
import org.jetbrains.kotlin.config.JvmTarget;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
@@ -218,7 +217,7 @@ public class FunctionCodegen {
flags,
asmMethod.getName(),
asmMethod.getDescriptor(),
jvmSignature.getGenericsSignature(),
strategy.skipGenericSignature() ? null : jvmSignature.getGenericsSignature(),
getThrownExceptions(functionDescriptor, typeMapper)
),
flags, asmMethod.getName(),
@@ -1546,13 +1545,15 @@ public class FunctionCodegen {
public void genSamDelegate(@NotNull FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenDescriptor, StackValue field) {
FunctionDescriptor delegatedTo = overriddenDescriptor.getOriginal();
JvmDeclarationOrigin declarationOrigin =
JvmDeclarationOriginKt.SamDelegation(functionDescriptor);
JvmDeclarationOrigin declarationOrigin = JvmDeclarationOriginKt.SamDelegation(functionDescriptor);
// Skip writing generic signature for the SAM wrapper class method because it may reference type parameters from the SAM interface
// which would make little sense outside of that interface and may break Java reflection.
// E.g. functionDescriptor for a SAM wrapper for java.util.function.Predicate is the method `test` with signature "(T) -> Boolean"
genDelegate(
functionDescriptor, delegatedTo,
declarationOrigin,
functionDescriptor, delegatedTo, declarationOrigin,
(ClassDescriptor) overriddenDescriptor.getContainingDeclaration(),
field);
field, true
);
}
public void genDelegate(@NotNull FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenDescriptor, StackValue field) {
@@ -1568,7 +1569,7 @@ public class FunctionCodegen {
) {
JvmDeclarationOrigin declarationOrigin =
JvmDeclarationOriginKt.Delegation(DescriptorToSourceUtils.descriptorToDeclaration(delegatedTo), delegateFunction);
genDelegate(delegateFunction, delegatedTo, declarationOrigin, toClass, field);
genDelegate(delegateFunction, delegatedTo, declarationOrigin, toClass, field, false);
}
private void genDelegate(
@@ -1576,7 +1577,8 @@ public class FunctionCodegen {
FunctionDescriptor delegatedTo,
@NotNull JvmDeclarationOrigin declarationOrigin,
ClassDescriptor toClass,
StackValue field
StackValue field,
boolean skipGenericSignature
) {
generateMethod(
declarationOrigin, delegateFunction,
@@ -1631,6 +1633,11 @@ public class FunctionCodegen {
public boolean skipNotNullAssertionsForParameters() {
return false;
}
@Override
public boolean skipGenericSignature() {
return skipGenericSignature;
}
}
);
}
@@ -28,6 +28,10 @@ public abstract class FunctionGenerationStrategy {
public abstract boolean skipNotNullAssertionsForParameters();
public boolean skipGenericSignature() {
return false;
}
public MethodVisitor wrapMethodVisitor(@NotNull MethodVisitor mv, int access, @NotNull String name, @NotNull String desc) {
return mv;
}
@@ -0,0 +1,32 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FILE: J.java
import java.util.*;
public interface J<T extends Number> {
T foo(List<T> p0, Map<T, ? extends Set<T>> p1);
}
// FILE: K.kt
import kotlin.test.assertEquals
object O : J<Long> {
override fun foo(p0: List<Long>, p1: Map<Long, out Set<Long>>): Long = 42L
}
class A : J<Long> by O
fun box(): String {
val m = A::class.java.getDeclaredMethod("foo", List::class.java, Map::class.java)
assertEquals(
"[interface java.util.List, interface java.util.Map]",
m.parameterTypes.contentToString()
)
assertEquals(
"[java.util.List<java.lang.Long>, java.util.Map<java.lang.Long, ? extends java.util.Set<java.lang.Long>>]",
m.genericParameterTypes.contentToString()
)
return "OK"
}
@@ -0,0 +1,50 @@
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FULL_JDK
// FILE: Java.java
import java.lang.reflect.Method;
import java.util.function.Predicate;
import java.util.*;
public final class Java {
public static Method getTest(Predicate<Object> predicate) throws NoSuchMethodException {
return predicate.getClass().getMethod("test", Object.class);
}
public static Method getFoo(ComplexPredicate<Long> predicate) throws NoSuchMethodException {
return predicate.getClass().getMethod("foo", Number.class, List.class, Map.class);
}
}
// FILE: ComplexPredicate.java
import java.util.*;
public interface ComplexPredicate<T extends Number> {
boolean foo(T p0, List<T> p1, Map<T, ? extends Set<T>> p2);
}
// FILE: K.kt
import java.lang.reflect.Method
import java.util.*
import kotlin.test.assertEquals
fun check(title: String, expected: String, method: Method) {
assertEquals(expected, method.parameterTypes.contentToString(), "Fail parameterTypes of $title")
assertEquals(expected, method.genericParameterTypes.contentToString(), "Fail genericParameterTypes of $title")
}
private fun bar(p0: Long, p1: List<Long>, p2: Map<Long, Set<Long>>) = true
fun box(): String {
check("SAM-implementing lambda 1", "[class java.lang.Object]", Java.getTest { Objects.nonNull(it) })
check("SAM-wrapped function reference 1", "[class java.lang.Object]", Java.getTest(Objects::nonNull))
check("SAM-implementing lambda 2", "[class java.lang.Number, interface java.util.List, interface java.util.Map]", Java.getFoo { p0, p1, p2 -> bar(p0, p1, p2) })
check("SAM-wrapped function reference 2", "[class java.lang.Number, interface java.util.List, interface java.util.Map]", Java.getFoo(::bar))
return "OK"
}
@@ -17601,6 +17601,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/genericSignature/defaultImplsGenericSignature.kt");
}
@TestMetadata("delegatedMembers.kt")
public void testDelegatedMembers() throws Exception {
runTest("compiler/testData/codegen/box/reflection/genericSignature/delegatedMembers.kt");
}
@TestMetadata("functionLiteralGenericSignature.kt")
public void testFunctionLiteralGenericSignature() throws Exception {
runTest("compiler/testData/codegen/box/reflection/genericSignature/functionLiteralGenericSignature.kt");
@@ -17631,6 +17636,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/genericSignature/kt6106.kt");
}
@TestMetadata("samWrappedLambdaVsReference.kt")
public void testSamWrappedLambdaVsReference() throws Exception {
runTest("compiler/testData/codegen/box/reflection/genericSignature/samWrappedLambdaVsReference.kt");
}
@TestMetadata("signatureOfDeepGenericInner.kt")
public void testSignatureOfDeepGenericInner() throws Exception {
runTest("compiler/testData/codegen/box/reflection/genericSignature/signatureOfDeepGenericInner.kt");
@@ -17601,6 +17601,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/reflection/genericSignature/defaultImplsGenericSignature.kt");
}
@TestMetadata("delegatedMembers.kt")
public void testDelegatedMembers() throws Exception {
runTest("compiler/testData/codegen/box/reflection/genericSignature/delegatedMembers.kt");
}
@TestMetadata("functionLiteralGenericSignature.kt")
public void testFunctionLiteralGenericSignature() throws Exception {
runTest("compiler/testData/codegen/box/reflection/genericSignature/functionLiteralGenericSignature.kt");
@@ -17631,6 +17636,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/reflection/genericSignature/kt6106.kt");
}
@TestMetadata("samWrappedLambdaVsReference.kt")
public void testSamWrappedLambdaVsReference() throws Exception {
runTest("compiler/testData/codegen/box/reflection/genericSignature/samWrappedLambdaVsReference.kt");
}
@TestMetadata("signatureOfDeepGenericInner.kt")
public void testSignatureOfDeepGenericInner() throws Exception {
runTest("compiler/testData/codegen/box/reflection/genericSignature/signatureOfDeepGenericInner.kt");
@@ -17601,6 +17601,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/reflection/genericSignature/defaultImplsGenericSignature.kt");
}
@TestMetadata("delegatedMembers.kt")
public void testDelegatedMembers() throws Exception {
runTest("compiler/testData/codegen/box/reflection/genericSignature/delegatedMembers.kt");
}
@TestMetadata("functionLiteralGenericSignature.kt")
public void testFunctionLiteralGenericSignature() throws Exception {
runTest("compiler/testData/codegen/box/reflection/genericSignature/functionLiteralGenericSignature.kt");
@@ -17631,6 +17636,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/reflection/genericSignature/kt6106.kt");
}
@TestMetadata("samWrappedLambdaVsReference.kt")
public void testSamWrappedLambdaVsReference() throws Exception {
runTest("compiler/testData/codegen/box/reflection/genericSignature/samWrappedLambdaVsReference.kt");
}
@TestMetadata("signatureOfDeepGenericInner.kt")
public void testSignatureOfDeepGenericInner() throws Exception {
runTest("compiler/testData/codegen/box/reflection/genericSignature/signatureOfDeepGenericInner.kt");