Do not generate generic signature for SAM wrapper methods
#KT-23870 Fixed
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
+32
@@ -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"
|
||||
}
|
||||
+50
@@ -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"
|
||||
}
|
||||
Generated
+10
@@ -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");
|
||||
|
||||
+10
@@ -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");
|
||||
|
||||
+10
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user