Support 'call' for references to inline class constructors

#KT-26748
This commit is contained in:
Dmitry Petrov
2018-10-17 10:12:16 +03:00
parent 94e1701089
commit 5032c106af
8 changed files with 81 additions and 5 deletions
@@ -0,0 +1,46 @@
// IGNORE_BACKEND: JS_IR, JS, NATIVE, JVM_IR
// WITH_REFLECT
import kotlin.reflect.KCallable
import kotlin.test.assertEquals
inline class Z(val x: Int) {
constructor(a: Int, b: Int) : this(a + b)
}
inline class L(val x: Long) {
constructor(a: Long, b: Long) : this(a + b)
}
inline class S(val x: String) {
constructor(a: String, b: String) : this(a + b)
}
inline class A(val x: Any) {
constructor(a: String, b: String) : this(a + b)
}
inline class Z2(val z: Z)
fun box(): String {
val ctorZ1: (Int) -> Z = ::Z
val ctorZ2: (Int, Int) -> Z = ::Z
val ctorL1: (Long) -> L = ::L
val ctorL2: (Long, Long) -> L = ::L
val ctorS1: (String) -> S = ::S
val ctorS2: (String, String) -> S = ::S
val ctorA1: (Any) -> A = ::A
val ctorA2: (String, String) -> A = ::A
assertEquals(Z(42), (ctorZ1 as KCallable<Z>).call(42))
assertEquals(Z(123), (ctorZ2 as KCallable<Z>).call(100, 23))
assertEquals(L(1L), (ctorL1 as KCallable<L>).call(1L))
assertEquals(L(123L), (ctorL2 as KCallable<L>).call(100L, 23L))
assertEquals(S("abc"), (ctorS1 as KCallable<S>).call("abc"))
assertEquals(S("abc"), (ctorS2 as KCallable<S>).call("ab", "c"))
assertEquals(A("abc"), (ctorA1 as KCallable<A>).call("abc"))
assertEquals(A("abc"), (ctorA2 as KCallable<A>).call("a", "bc"))
assertEquals(Z2(Z(42)), ::Z2.call(Z(42)))
return "OK"
}
@@ -18535,6 +18535,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/functionsAndConstructors.kt");
}
@TestMetadata("inlineClassConstructor.kt")
public void testInlineClassConstructor() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/inlineClassConstructor.kt");
}
@TestMetadata("jvmStaticFieldInObject.kt")
public void testJvmStaticFieldInObject() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/jvmStaticFieldInObject.kt");
@@ -18535,6 +18535,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/functionsAndConstructors.kt");
}
@TestMetadata("inlineClassConstructor.kt")
public void testInlineClassConstructor() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/inlineClassConstructor.kt");
}
@TestMetadata("jvmStaticFieldInObject.kt")
public void testJvmStaticFieldInObject() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/jvmStaticFieldInObject.kt");
@@ -18540,6 +18540,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/functionsAndConstructors.kt");
}
@TestMetadata("inlineClassConstructor.kt")
public void testInlineClassConstructor() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/inlineClassConstructor.kt");
}
@TestMetadata("jvmStaticFieldInObject.kt")
public void testJvmStaticFieldInObject() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/jvmStaticFieldInObject.kt");
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.name.NameUtils
import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
import org.jetbrains.kotlin.resolve.isInlineClass
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
@@ -107,7 +108,7 @@ internal sealed class JvmPropertySignature {
} else {
val (name, desc) =
JvmProtoBufUtil.getJvmFieldSignature(proto, nameResolver, typeTable)
?: throw KotlinReflectionInternalError("No field signature for property: $descriptor")
?: throw KotlinReflectionInternalError("No field signature for property: $descriptor")
JvmAbi.getterName(name) + getManglingSuffix() + "()" + desc
}
@@ -116,7 +117,7 @@ internal sealed class JvmPropertySignature {
if (descriptor.visibility == Visibilities.INTERNAL && containingDeclaration is DeserializedClassDescriptor) {
val classProto = containingDeclaration.classProto
val moduleName = classProto.getExtensionOrNull(JvmProtoBuf.classModuleName)?.let(nameResolver::getString)
?: JvmAbi.DEFAULT_MODULE_NAME
?: JvmAbi.DEFAULT_MODULE_NAME
return "$" + NameUtils.sanitizeAsJavaIdentifier(moduleName)
}
if (descriptor.visibility == Visibilities.PRIVATE && containingDeclaration is PackageFragmentDescriptor) {
@@ -172,14 +173,17 @@ internal object RuntimeTypeMapper {
}
if (proto is ProtoBuf.Constructor) {
JvmProtoBufUtil.getJvmConstructorSignature(proto, function.nameResolver, function.typeTable)?.let { signature ->
return JvmFunctionSignature.KotlinConstructor(signature)
return if (possiblySubstitutedFunction.containingDeclaration.isInlineClass())
JvmFunctionSignature.KotlinFunction(signature)
else
JvmFunctionSignature.KotlinConstructor(signature)
}
}
return mapJvmFunctionSignature(function)
}
is JavaMethodDescriptor -> {
val method = ((function.source as? JavaSourceElement)?.javaElement as? ReflectJavaMethod)?.member
?: throw KotlinReflectionInternalError("Incorrect resolution sequence for Java method $function")
?: throw KotlinReflectionInternalError("Incorrect resolution sequence for Java method $function")
return JvmFunctionSignature.JavaMethod(method)
}
@@ -7,6 +7,7 @@ package kotlin.reflect.jvm.internal.calls
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
@@ -69,7 +70,7 @@ internal class InlineClassAwareCaller<out M : Member>(
val extensionReceiverType = descriptor.extensionReceiverParameter?.type
if (extensionReceiverType != null) {
kotlinParameterTypes.add(extensionReceiverType)
} else {
} else if (descriptor !is ConstructorDescriptor) {
val containingDeclaration = descriptor.containingDeclaration
if (containingDeclaration is ClassDescriptor && containingDeclaration.isInline) {
kotlinParameterTypes.add(containingDeclaration.defaultType)
@@ -16640,6 +16640,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/functionsAndConstructors.kt");
}
@TestMetadata("inlineClassConstructor.kt")
public void testInlineClassConstructor() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/inlineClassConstructor.kt");
}
@TestMetadata("jvmStaticFieldInObject.kt")
public void testJvmStaticFieldInObject() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/jvmStaticFieldInObject.kt");
@@ -17685,6 +17685,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/functionsAndConstructors.kt");
}
@TestMetadata("inlineClassConstructor.kt")
public void testInlineClassConstructor() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/inlineClassConstructor.kt");
}
@TestMetadata("jvmStaticFieldInObject.kt")
public void testJvmStaticFieldInObject() throws Exception {
runTest("compiler/testData/codegen/box/reflection/call/inlineClasses/jvmStaticFieldInObject.kt");