From e74e267d16c90696522f8a2b42699b41fc2fbbe6 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Mon, 20 Sep 2021 23:25:18 +0200 Subject: [PATCH] Inline classes. Use inline class instead of underlying type in annotations if underlying type is not nullable reference type. Previously, it worked only for inline classes with primitive underlying type and nullable reference type. #KT-44133 --- .../backend/jvm/codegen/AnnotationCodegen.kt | 12 +++--- .../box/inlineClasses/kclassInAnnotation.kt | 38 ++++++++++++++++--- .../LightAnalysisModeTestGenerated.java | 10 ++--- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt index baf06478bbe..99b32477051 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/AnnotationCodegen.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmSymbols +import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType import org.jetbrains.kotlin.backend.jvm.ir.isWithFlexibleNullability import org.jetbrains.kotlin.builtins.StandardNames @@ -38,6 +39,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.types.impl.buildSimpleType import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.name.FqName @@ -275,12 +277,12 @@ abstract class AnnotationCodegen( visitor.visitEnd() } is IrClassReference -> { - var classType = value.classType + val classType = value.classType classType.classOrNull?.owner?.let(innerClassConsumer::addInnerClassInfoFromAnnotation) - if (classType.isInlineClassType()) { - classType = classType.makeNullable() - } - annotationVisitor.visit(name, typeMapper.mapType(classType)) + val mappedType = + if (classType.isInlineClassType()) typeMapper.mapClass(classType.erasedUpperBound) + else typeMapper.mapType(classType) + annotationVisitor.visit(name, mappedType) } is IrErrorExpression -> error("Don't know how to compile annotation value ${ir2string(value)}") else -> error("Unsupported compile-time value ${ir2string(value)}") diff --git a/compiler/testData/codegen/box/inlineClasses/kclassInAnnotation.kt b/compiler/testData/codegen/box/inlineClasses/kclassInAnnotation.kt index d76a73f1a8a..ef03392f74f 100644 --- a/compiler/testData/codegen/box/inlineClasses/kclassInAnnotation.kt +++ b/compiler/testData/codegen/box/inlineClasses/kclassInAnnotation.kt @@ -1,17 +1,45 @@ // WITH_REFLECT // TARGET_BACKEND: JVM +// IGNORE_BACKEND: JVM package test import kotlin.reflect.KClass -inline class IC(val i: Int) +@JvmInline +value class ICInt(val i: Int) + +@JvmInline +value class ICIntN(val i: Int?) + +@JvmInline +value class ICAny(val a: Any) annotation class Ann(val c: KClass<*>) -@Ann(IC::class) -class C +@Ann(ICInt::class) +class CInt + +@Ann(ICIntN::class) +class CIntN + +@Ann(ICAny::class) +class CAny + +@Ann(Result::class) +class CResult fun box(): String { - val klass = (C::class.annotations.first() as Ann).c.toString() - return if (klass == "class test.IC") "OK" else klass + var klass = (CInt::class.annotations.first() as Ann).c.toString() + if (klass != "class test.ICInt") return "Expected class test.ICInt, got $klass" + + klass = (CIntN::class.annotations.first() as Ann).c.toString() + if (klass != "class test.ICIntN") return "Expected class test.ICIntN, got $klass" + + klass = (CAny::class.annotations.first() as Ann).c.toString() + if (klass != "class test.ICAny") return "Expected class test.ICAny, got $klass" + + klass = (CResult::class.annotations.first() as Ann).c.toString() + if (klass != "class kotlin.Result") return "Expected class kotlin.Result, got $klass" + + return "OK" } \ No newline at end of file diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 5a6dceaf4f3..54be4ca765b 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -15174,6 +15174,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/inlineClassWithCustomEquals.kt"); } + @TestMetadata("kclassInAnnotation.kt") + public void ignoreKclassInAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/kclassInAnnotation.kt"); + } + @TestMetadata("kt31994.kt") public void ignoreKt31994() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/kt31994.kt"); @@ -15702,11 +15707,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/jvmStaticVarInInlineClassCompanion.kt"); } - @TestMetadata("kclassInAnnotation.kt") - public void testKclassInAnnotation() throws Exception { - runTest("compiler/testData/codegen/box/inlineClasses/kclassInAnnotation.kt"); - } - @TestMetadata("kt25246.kt") public void testKt25246() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/kt25246.kt");