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.codegen.state.KotlinTypeMapper;
|
||||||
import org.jetbrains.kotlin.config.JvmDefaultMode;
|
import org.jetbrains.kotlin.config.JvmDefaultMode;
|
||||||
import org.jetbrains.kotlin.config.JvmTarget;
|
import org.jetbrains.kotlin.config.JvmTarget;
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||||
@@ -218,7 +217,7 @@ public class FunctionCodegen {
|
|||||||
flags,
|
flags,
|
||||||
asmMethod.getName(),
|
asmMethod.getName(),
|
||||||
asmMethod.getDescriptor(),
|
asmMethod.getDescriptor(),
|
||||||
jvmSignature.getGenericsSignature(),
|
strategy.skipGenericSignature() ? null : jvmSignature.getGenericsSignature(),
|
||||||
getThrownExceptions(functionDescriptor, typeMapper)
|
getThrownExceptions(functionDescriptor, typeMapper)
|
||||||
),
|
),
|
||||||
flags, asmMethod.getName(),
|
flags, asmMethod.getName(),
|
||||||
@@ -1546,13 +1545,15 @@ public class FunctionCodegen {
|
|||||||
|
|
||||||
public void genSamDelegate(@NotNull FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenDescriptor, StackValue field) {
|
public void genSamDelegate(@NotNull FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenDescriptor, StackValue field) {
|
||||||
FunctionDescriptor delegatedTo = overriddenDescriptor.getOriginal();
|
FunctionDescriptor delegatedTo = overriddenDescriptor.getOriginal();
|
||||||
JvmDeclarationOrigin declarationOrigin =
|
JvmDeclarationOrigin declarationOrigin = JvmDeclarationOriginKt.SamDelegation(functionDescriptor);
|
||||||
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(
|
genDelegate(
|
||||||
functionDescriptor, delegatedTo,
|
functionDescriptor, delegatedTo, declarationOrigin,
|
||||||
declarationOrigin,
|
|
||||||
(ClassDescriptor) overriddenDescriptor.getContainingDeclaration(),
|
(ClassDescriptor) overriddenDescriptor.getContainingDeclaration(),
|
||||||
field);
|
field, true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void genDelegate(@NotNull FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenDescriptor, StackValue field) {
|
public void genDelegate(@NotNull FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenDescriptor, StackValue field) {
|
||||||
@@ -1568,7 +1569,7 @@ public class FunctionCodegen {
|
|||||||
) {
|
) {
|
||||||
JvmDeclarationOrigin declarationOrigin =
|
JvmDeclarationOrigin declarationOrigin =
|
||||||
JvmDeclarationOriginKt.Delegation(DescriptorToSourceUtils.descriptorToDeclaration(delegatedTo), delegateFunction);
|
JvmDeclarationOriginKt.Delegation(DescriptorToSourceUtils.descriptorToDeclaration(delegatedTo), delegateFunction);
|
||||||
genDelegate(delegateFunction, delegatedTo, declarationOrigin, toClass, field);
|
genDelegate(delegateFunction, delegatedTo, declarationOrigin, toClass, field, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void genDelegate(
|
private void genDelegate(
|
||||||
@@ -1576,7 +1577,8 @@ public class FunctionCodegen {
|
|||||||
FunctionDescriptor delegatedTo,
|
FunctionDescriptor delegatedTo,
|
||||||
@NotNull JvmDeclarationOrigin declarationOrigin,
|
@NotNull JvmDeclarationOrigin declarationOrigin,
|
||||||
ClassDescriptor toClass,
|
ClassDescriptor toClass,
|
||||||
StackValue field
|
StackValue field,
|
||||||
|
boolean skipGenericSignature
|
||||||
) {
|
) {
|
||||||
generateMethod(
|
generateMethod(
|
||||||
declarationOrigin, delegateFunction,
|
declarationOrigin, delegateFunction,
|
||||||
@@ -1631,6 +1633,11 @@ public class FunctionCodegen {
|
|||||||
public boolean skipNotNullAssertionsForParameters() {
|
public boolean skipNotNullAssertionsForParameters() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean skipGenericSignature() {
|
||||||
|
return skipGenericSignature;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ public abstract class FunctionGenerationStrategy {
|
|||||||
|
|
||||||
public abstract boolean skipNotNullAssertionsForParameters();
|
public abstract boolean skipNotNullAssertionsForParameters();
|
||||||
|
|
||||||
|
public boolean skipGenericSignature() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public MethodVisitor wrapMethodVisitor(@NotNull MethodVisitor mv, int access, @NotNull String name, @NotNull String desc) {
|
public MethodVisitor wrapMethodVisitor(@NotNull MethodVisitor mv, int access, @NotNull String name, @NotNull String desc) {
|
||||||
return mv;
|
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");
|
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")
|
@TestMetadata("functionLiteralGenericSignature.kt")
|
||||||
public void testFunctionLiteralGenericSignature() throws Exception {
|
public void testFunctionLiteralGenericSignature() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/genericSignature/functionLiteralGenericSignature.kt");
|
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");
|
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")
|
@TestMetadata("signatureOfDeepGenericInner.kt")
|
||||||
public void testSignatureOfDeepGenericInner() throws Exception {
|
public void testSignatureOfDeepGenericInner() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/genericSignature/signatureOfDeepGenericInner.kt");
|
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");
|
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")
|
@TestMetadata("functionLiteralGenericSignature.kt")
|
||||||
public void testFunctionLiteralGenericSignature() throws Exception {
|
public void testFunctionLiteralGenericSignature() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/genericSignature/functionLiteralGenericSignature.kt");
|
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");
|
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")
|
@TestMetadata("signatureOfDeepGenericInner.kt")
|
||||||
public void testSignatureOfDeepGenericInner() throws Exception {
|
public void testSignatureOfDeepGenericInner() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/genericSignature/signatureOfDeepGenericInner.kt");
|
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");
|
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")
|
@TestMetadata("functionLiteralGenericSignature.kt")
|
||||||
public void testFunctionLiteralGenericSignature() throws Exception {
|
public void testFunctionLiteralGenericSignature() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/genericSignature/functionLiteralGenericSignature.kt");
|
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");
|
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")
|
@TestMetadata("signatureOfDeepGenericInner.kt")
|
||||||
public void testSignatureOfDeepGenericInner() throws Exception {
|
public void testSignatureOfDeepGenericInner() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/genericSignature/signatureOfDeepGenericInner.kt");
|
runTest("compiler/testData/codegen/box/reflection/genericSignature/signatureOfDeepGenericInner.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user