From 090d3327c04ba45f8edb4517300b22ad445a0a48 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Wed, 14 Nov 2018 14:06:54 +0300 Subject: [PATCH] Use wrapper class of an inline one as a result for `javaClass` #KT-28185 Fixed #KT-28246 Open --- .../codegen/intrinsics/JavaClassProperty.kt | 23 ++++++++- .../javaClassIntrinsicOnInlineClasses.kt | 50 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 ++ .../LightAnalysisModeTestGenerated.java | 5 ++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 ++ 5 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/codegen/box/inlineClasses/javaClassIntrinsicOnInlineClasses.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/JavaClassProperty.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/JavaClassProperty.kt index 62a9df2a4d8..8deb53fe81c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/JavaClassProperty.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/JavaClassProperty.kt @@ -24,6 +24,8 @@ import org.jetbrains.kotlin.codegen.ExpressionCodegen import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.isInlineClassType +import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.AsmTypes.UNIT_TYPE import org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType import org.jetbrains.org.objectweb.asm.Type @@ -42,13 +44,29 @@ object JavaClassProperty : IntrinsicPropertyGetter() { } fun generateImpl(v: InstructionAdapter, receiver: StackValue): Type { + fun invokeVirtualGetClassMethod() { + v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false) + } + val type = receiver.type + val kotlinType = receiver.kotlinType when { type == Type.VOID_TYPE -> { receiver.put(Type.VOID_TYPE, v) StackValue.unit().put(UNIT_TYPE, v) - v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false) + invokeVirtualGetClassMethod() } + + kotlinType?.isInlineClassType() == true -> { + receiver.put(type, kotlinType, v) + StackValue.coerce( + type, kotlinType, + AsmTypes.OBJECT_TYPE, kotlinType.constructor.builtIns.nullableAnyType, + v + ) + invokeVirtualGetClassMethod() + } + isPrimitive(type) -> { if (!StackValue.couldSkipReceiverOnStaticCall(receiver)) { receiver.put(type, v) @@ -56,9 +74,10 @@ object JavaClassProperty : IntrinsicPropertyGetter() { } v.getstatic(boxType(type).internalName, "TYPE", "Ljava/lang/Class;") } + else -> { receiver.put(type, v) - v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false) + invokeVirtualGetClassMethod() } } diff --git a/compiler/testData/codegen/box/inlineClasses/javaClassIntrinsicOnInlineClasses.kt b/compiler/testData/codegen/box/inlineClasses/javaClassIntrinsicOnInlineClasses.kt new file mode 100644 index 00000000000..e245d514c97 --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/javaClassIntrinsicOnInlineClasses.kt @@ -0,0 +1,50 @@ +// WITH_RUNTIME +// TARGET_BACKEND: JVM +// IGNORE_BACKEND: JVM_IR + +package root + +inline class IcInt(val x: Int) +inline class IcLong(val l: Long) +inline class IcAny(val a: Any?) +inline class IcOverIc(val o: IcLong) + +fun check(c: Class<*>, s: String) { + if (c.toString() != s) error("Fail, expected: $s, actual: $c") +} + +fun box(): String { + val i = IcInt(0) + val l = IcLong(0) + val a = IcAny("foo") + val o = IcOverIc(IcLong(0)) + + check(i.javaClass, "class root.IcInt") + check(l.javaClass, "class root.IcLong") + check(a.javaClass, "class root.IcAny") + check(o.javaClass, "class root.IcOverIc") + check(1u.javaClass, "class kotlin.UInt") + + check(i::class.java, "class root.IcInt") + check(l::class.java, "class root.IcLong") + check(a::class.java, "class root.IcAny") + check(o::class.java, "class root.IcOverIc") + check(1u::class.java, "class kotlin.UInt") + + val arrI = arrayOf(i) + check(arrI[0].javaClass, "class root.IcInt") + + val arrL = arrayOf(l) + check(arrL[0].javaClass, "class root.IcLong") + + val arrA = arrayOf(a) + check(arrA[0].javaClass, "class root.IcAny") + + val arrO = arrayOf(o) + check(arrO[0].javaClass, "class root.IcOverIc") + + val arrU = arrayOf(1u) + check(arrU[0].javaClass, "class kotlin.UInt") + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index e7dde7f46f5..35eef4d253f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -11970,6 +11970,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inlineClasses/iterateOverListOfInlineClassValues.kt"); } + @TestMetadata("javaClassIntrinsicOnInlineClasses.kt") + public void testJavaClassIntrinsicOnInlineClasses() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/javaClassIntrinsicOnInlineClasses.kt"); + } + @TestMetadata("jvmFieldInInlineClassCompanion.kt") public void testJvmFieldInInlineClassCompanion() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/jvmFieldInInlineClassCompanion.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index e67c42d15f4..fb7e3315065 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -11970,6 +11970,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/iterateOverListOfInlineClassValues.kt"); } + @TestMetadata("javaClassIntrinsicOnInlineClasses.kt") + public void testJavaClassIntrinsicOnInlineClasses() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/javaClassIntrinsicOnInlineClasses.kt"); + } + @TestMetadata("jvmFieldInInlineClassCompanion.kt") public void testJvmFieldInInlineClassCompanion() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/jvmFieldInInlineClassCompanion.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 9f42c66437a..833de931130 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -11975,6 +11975,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/iterateOverListOfInlineClassValues.kt"); } + @TestMetadata("javaClassIntrinsicOnInlineClasses.kt") + public void testJavaClassIntrinsicOnInlineClasses() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/javaClassIntrinsicOnInlineClasses.kt"); + } + @TestMetadata("jvmFieldInInlineClassCompanion.kt") public void testJvmFieldInInlineClassCompanion() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/jvmFieldInInlineClassCompanion.kt");